LESS mixin with parameters syntax error - css

I've got the following mixin that adjusts the width and padding of an item to cope with IE7's lack of support for box-sizing:border-box. It gives me a syntax on & .width(#width: 100, #paddinglr: 0)
I appreciate this is missing a % but any ideas why it's breaking?
.width(#width: 100, #paddinglr: 0) {
width: #width;
padding: #paddinglr;
}
body {
&.lt-ie8 {
& .width(#width: 100, #paddinglr: 0) {
width: #width-#paddinglr;
padding: #paddinglr;
}
}
}

You cannot define a mixin as a selector string, so & .width() for your nested portion cannot be a mixin definition (which is what you have tried to make it).
I think what you are trying to do is make a generic .width() mixin to use on any particular element. It appears that you intend to just set a single number for padding, which is fine.
However, it also appears that (based off your % comment), that you expect this code to produce a width value that is 100% of the parent minus the value of the padding. This is okay, too, assuming you are using percentages for padding also. If you are not, but intend instead that the padding be a pixel value, that mixed units cannot be done by LESS as you might expect, as LESS is a preprocessor, so it is not dynamic in the sense of being able to detect the width of the parent based off the percent at run time and then subtract the padding pixel value.
Now, if your intentions are percentages, or any equal measurement values for both width and padding (whether both px, both em units, etc.), then you can get what you desire by various means. One of the many solutions would be by overriding the .width() mixin within the .lt-ie8 nest, so for example:
.width(#width: 100%, #paddinglr: 0) {
width: #width;
padding: #paddinglr;
}
body {
.someDiv {
.width(100%, 10%);
}
&.lt-ie8 {
/* here is the override of the mixin */
.width(#width: 100%, #paddinglr: 0) {
/* note, I believe you will want to multiply the padding by 2 for the width change due to left and right padding */
width: #width - (2 * #paddinglr);
padding: #paddinglr;
}
/* and here is the override of the actual css */
.someDiv {
.width(100%, 10%);
}
}
}
Which produces this CSS (minus the comments above which were just to communicate to you):
body .someDiv {
width: 100%;
padding: 10%;
}
body.lt-ie8 .someDiv {
width: 80%;
padding: 10%;
}

Related

Why isn't there a shorthand property for width and height in CSS?

Wouldn't it be faster to use a shorter property for an item's width and height when coding in CSS?
As of now I have to type:
selector {width: 100px; height: 250px;}
Which is fast as it is, but I reckon that this would be faster:
selector {dimension: 100px 250px;}
Is there already a CSS pre-processor that can achieve this? Seems like it would save a bit of time when doing lots of width's and height's.
A good example could be the CSS Grid properties:
grid-template-columns: 100px 100px;
grid-template-rows: 100px 100px;
Would be the same as:
grid-template: 100px 100px / 100px 100px;
Short answer: The CSSWG couldn't agree on a name for the shorthand property yet.
The idea isn't new and a lot of people suggested it every now and then over the years. However, there's a current proposal [css-sizing] Adding a 'size' shorthand for 'width'/'height' from the CSSWG (CSS Working Group).
A lot of things have been discussed already, but a few are still unresolved. Here are some examples:
What is the proper name?
Some of the names that where suggested:
size: clashes with the #page's size-property
dimensions: probably too long or difficult to spell
box-size: probably too close to box-sizing
How will it work?
Should it be:
<box-size>: <width> <height>?
… or closer related to other properties like padding or margin:
<box-size>: <height> <width>?
Also: Should it support an additional parameter that will keep the aspect ratio?
Who's going to support it?
Which vendors will support the proposal and the syntax itself?
Will it enhance the author's experience, so that people will actually use it?
As you can see, there might be a shorthand notation in the future, as the CSSWG said recently in their Minutes Telecon on 2017-08-16:
The group agreed that a shorthand for ‘width’/’height’ would be good, but shouldn’t be called ‘size’. However, there wasn’t time to come up with a different name.
That being said, of course you can use a CSS pre-processor, to make your life easier. For example, I have a mixin in LESS, that looks like this:
.size(#a: null, #b: null) {
& when not (null = #a) {
width: #a;
}
& when (null = #b) {
height: #a;
}
& when not (null = #b) {
height: #b;
}
}
Which is as simple as this:
.size(100%, 50%);
width: 100%;
height: 50%;
… and it supports square elements as well:
.size(100%);
width: 100%;
height: 100%;
Is a good idea but at this moment official specifications do not allow it.
That's all.
My suggestion(just an opinion/PoV) would be:
Replace size as a shorthand for the height and width of a selected element.
Example:
size: <height> <width>;
size: 420px 297px;
size: 100% 50%;
size: 15rem 5em;
Now about the previous property of size used with #page should be changed to page-size.
Example:
Source: MDN Web Docs
/* Keyword values for scalable size */
page-size: auto;
page-size: portrait;
page-size: landscape;
/* <length> values */
/* 1 value: height = width */
page-size: 6in;
/* 2 values: width then height */
page-size: 4in 6in;
/* Keyword values for absolute size */
page-size: A4;
page-size: B5;
page-size: JIS-B4;
page-size: letter;
/* Mixing size and orientation */
page-size: A4 portrait;

CSS calc() behaviour in CSS variables

I'm curious to the behaviour of using calc() in setting a CSS variable.
Example:
#test {
--halfWidth: calc(100% / 2);
}
Now, if the #test element, say a div, was 500px wide, I would like the --halfWidth variable to be set to 250px.
But, as far as I can tell the var(--halfWidth) code used elsewhere simply drops in the calc(100% / 2) string instead of 250px. Which means that I can't use the calculation of say element A and use it in element B later on, since it would simply set for example width: var(--halfWidth); as half the width of element B instead of half the width of element A, where the variable was defined.
I've scoured the web trying to find any documentation on the behaviour of this, but I have so far drawn a blank.
Ideally, setting a CSS variable using calc should be available in two variants:
One variant working just like this example, simply dropping in the string as-is, bar any in-string variable replacements.
A second variant where calc() would yield the result of the calculation instead of simply replacing the string.
How to achieve this? I'd rather leave the actual implementation to people suited to it, but one possibility would be an eval() kind of thing; like eval(calc(100% / 2)) would give the result 250px.
Anyway, if anyone have any real documentation on this behaviour or a solution to how to get the example above to yield the result instead, I'm all ears!
Edit: Just FYI, I have read the specs at https://drafts.csswg.org/css-variables/
This is kind of a tough question to answer cause the answer will not be:
Do it like this...then it will work
The problem you are facing is the normal behavior of CSS. It cascades the styles. If what you are trying to achieve would work it would get real messy after a short amount of time.
I mean how cool is it that you can define a variable like this
#test {
--halfWidth: calc(100% / 2);
}
where var(--halfWidth) should always be calc(100% / 2). Did you note that it will always be half the width of the parent element?
Imagine how strange it would be if a programmer in a few months reads your code and has box with a width of 1000px set with --halfWidth and now it is 250px wide ... I would think the internet is broken :) It should just be 500px wide.
To achieve what you want, you could/should define different vars defining the widths of the parent elements. And split it down to the children.
One approach to this is to dynamically add a line to the CSS Object Model (CSSOM) which explicitly declares the width of the .halfwidth class.
This width will then apply to all divs with the .halfwidth class.
In the example below, I have, additionally, made .element-a horizontally resizable, so that you can see more clearly that as you change the width of .element-a, the width of both .halfwidth divs changes proportionately, including the .halfwidth div which is a child of .element-b.
Working Example:
let myStylesheet = document.styleSheets[0];
const elementA = document.getElementsByClassName('element-a')[0];
let elementAWidth = window.getComputedStyle(elementA).getPropertyValue('width');
const calculateHalfWidth = (elementAWidth) => {
myStylesheet.insertRule('.halfWidth { width: ' + (parseInt(elementAWidth) / 2) + 'px; }', myStylesheet.cssRules.length);
}
calculateHalfWidth(elementAWidth);
// ================================================================================
// THE SCRIPT BELOW USES A ResizeObserver TO WATCH THE RESIZABLE .element-a DIV
// ================================================================================
const elementAObserver = new ResizeObserver(entries => {
for (let entry of entries) {
if (entry.contentRect.width !== elementAWidth) {
calculateHalfWidth(entry.contentRect.width);
}
}
});
elementAObserver.observe(elementA);
body {
font-family: sans-serif;
}
div.element {
float: left;
width: 200px;
height: 100px;
margin: 12px 3px;
text-align: center;
border: 1px solid rgb(0, 0, 0);
}
div.element h2 {
font-size: 18px;
}
div.element-a {
resize: horizontal;
overflow: auto;
}
div.element-b {
width: 300px;
}
div.halfWidth {
height: 40px;
margin: 0 auto;
border: 1px dashed rgb(255, 0, 0);
}
div.halfWidth h2 {
font-size: 14px;
}
<div class="element element-a">
<h2>Element A</h2>
<div class="halfWidth">
<h2>halfWidth</h2>
</div>
</div>
<div class="element element-b">
<h2>Element B</h2>
<div class="halfWidth">
<h2>halfWidth</h2>
</div>
</div>

Getting the pixel value from a percentage in CSS/SASS [duplicate]

I want to be able to do the following:
height: 25% - 5px;
Obviously when I do that I get the error:
Incompatible units: 'px' and '%'.
Sass cannot perform arithmetic on values that cannot be converted from one unit to the next. Sass has no way of knowing exactly how wide "100%" is in terms of pixels or any other unit. That's something only the browser knows.
You need to use calc() instead. Check browser compatibility on Can I use...
.foo {
height: calc(25% - 5px);
}
If your values are in variables, you may need to use interpolation turn them into strings (otherwise Sass just tries to perform arithmetic):
$a: 25%;
$b: 5px;
.foo {
width: calc(#{$a} - #{$b});
}
There is a calc function in both SCSS [compile-time] and CSS [run-time]. You're likely invoking the former instead of the latter.
For obvious reasons mixing units won't work compile-time, but will at run-time.
You can force the latter by using unquote, a SCSS function.
.selector { height: unquote("-webkit-calc(100% - 40px)"); }
$var:25%;
$foo:5px;
.selector {
height:unquote("calc( #{$var} - #{$foo} )");
}
IF you know the width of the container, you could do like this:
#container
width: #{200}px
#element
width: #{(0.25 * 200) - 5}px
I'm aware that in many cases #container could have a relative width. Then this wouldn't work.
Sorry for reviving old thread - Compass' stretch with an :after pseudo-selector might suit your purpose - eg. if you want a div to fill width from left to (50% + 10px) of screen you could use (in SASS indented syntax):
.example
background: red
+stretch(0, -10px, 0, 0)
&:after
+stretch(0, 0, 0, 50%)
content: ' '
background: blue
The :after element fills 50% to the right of .example (leaving 50% available for .example's width), then .example is stretched to that width plus 10px.
Just add the percentage value into a variable and use #{$variable}
for example
$twentyFivePercent:25%;
.selector {
height: calc(#{$twentyFivePercent} - 5px);
}

Percentages with SASS - one pixel problems?

I want to build my minimal CSS framework. I did a grid system in SASS:
$width: 960px;
width: $width;
.grid-12 { width: $width; }
.grid-11 { width: percentage((($width/12)*11)/$width) }
.grid-10 { width: percentage((($width/12)*10)/$width) }
.grid-9 { width: percentage((($width/12)*9)/$width) }
.grid-8 { width: percentage((($width/12)*8)/$width) }
.grid-7 { width: percentage((($width/12)*7)/$width) }
.grid-6 { width: percentage(($width/2)/$width) }
.grid-5 { width: percentage((($width/12)*5)/$width) }
.grid-4 { width: percentage(($width/3)/$width) }
.grid-3 { width: percentage(($width/4)/$width) }
.grid-2 { width: percentage(($width/6)/$width) }
.grid-1 { width: percentage(($width/12)/$width) }
It works great, but sometimes - in some resolutions, eg. at my mobile with landscape view (960x540) some elements are 1px too short. It happens also when I resize browser.
What can I do?
some of the calculations will result in a number that can NOT be divided by 2
sometimes you will get .5px ...
and because of this . you will sometimes have 1 extra pixel
There is no "fix" for this. That's the way it is with all responsive layouts and grid systems. There are techniques like float isolation that can help keep your rounding errors from multiplying. Otherwise, 10 1px errors can turn into a 10px error. I wouldn't use that everywhere, but it's useful if you have a gallery-style layout with a lot of elements, all the same size, floating next to each other.
The real solution, mentioned in a comment above, is to adjust your design so that 1px rounding errors don't matter. If 1px can ruin your layout, responsive design isn't going to work.
You can't eliminate the rounding errors, but you have some control over where the missing pixels should go. By floating things left or right, and nesting in different ways, you can move the rounding errors where they will be least noticeable. Another solution is to apply layout (instead of float/width) to the last element in a row, and it will expand to fill the remaining space. The easiest way to apply layout is with overflow: hidden;, but that has some drawbacks.

Calculating width from percent to pixel then minus by pixel in LESS CSS

I will calculate width in some element from percent to pixel so I will minus -10px via using LESS and calc(). It´s possible?
div {
span {
width:calc(100% - 10px);
}
}
I using CSS3 calc() so it doesn't work: calc(100% - 10px)
Example: if 100% = 500px so width = 490px (500-10);
I made a demo for testing : http://jsfiddle.net/4DujZ/55/
so padding will say: 5 (10px / 2) all the time when I resizing.
Can I do it in LESS? I know how to do in jQuery and simple CSS like margin padding or else... but i will try to do functional in LESS with calc()
You can escape the calc arguments in order to prevent them from being evaluated on compilation.
Using your example, you would simply surround the arguments, like this:
calc(~'100% - 10px')
Demo : http://jsfiddle.net/c5aq20b6/
I find that I use this in one of the following three ways:
Basic Escaping
Everything inside the calc arguments is defined as a string, and is totally static until it's evaluated by the client:
LESS Input
div {
> span {
width: calc(~'100% - 10px');
}
}
CSS Output
div > span {
width: calc(100% - 10px);
}
Interpolation of Variables
You can insert a LESS variable into the string:
LESS Input
div {
> span {
#pad: 10px;
width: calc(~'100% - #{pad}');
}
}
CSS Output
div > span {
width: calc(100% - 10px);
}
Mixing Escaped and Compiled Values
You may want to escape a percentage value, but go ahead and evaluate something on compilation:
LESS Input
#btnWidth: 40px;
div {
> span {
#pad: 10px;
width: calc(~'(100% - #{pad})' - (#btnWidth * 2));
}
}
CSS Output
div > span {
width: calc((100% - 10px) - 80px);
}
Source: http://lesscss.org/functions/#string-functions-escape.
I think width: -moz-calc(25% - 1em); is what you are looking for.
And you may want to give this Link a look for any further assistance
Or, you could use the margin attribute like this:
{
background:#222;
width:100%;
height:100px;
margin-left: 10px;
margin-right: 10px;
display:block;
}
Try this :
width:auto;
margin-right:50px;

Resources