LESSCSS - use calculation and return value
LESS has no way as of yet to create a true "function," so we cope with it.
First
You can just use the unit function, like so:
LESS
.someClass { padding: unit(@basevalue, @unit); }
.someOtherClass { padding: unit(@basevalue*0.5, @unit); }
CSS
.someClass {
padding: 1em;
}
.someOtherClass {
padding: 0.5em;
}
Second
The mixins as functions is okay in some situations, but as you discovered, has the limitation of only setting the value once on the first call (and that is assuming a variable of the same name does not exist in that scope already).
LESS (first works right, second doesn't)
.returnUnit(@val:1) {
@return: unit(@basevalue*@val, @unit);
}
.someThirdClass {
.returnUnit(0.4);
padding: @return;
}
.someOoopsClass {
.returnUnit(0.4);
padding: @return;
.returnUnit(0.3);
margin: @return;
}
CSS Output
.someThirdClass {
padding: 0.4em;
}
.someOoopsClass {
padding: 0.4em;
margin: 0.4em; /* Ooops! Not 0.3em! */
}
Third
Limitation of the Second idea can be avoided by a second wrapping, as it isolates the scope for each variable returned by .returnUnit()
, like so:
LESS
.someAccurateClass {
& {
.returnUnit(0.4);
padding: @return;
}
& {
.returnUnit(0.3);
margin: @return;
}
}
CSS Output
.someAccurateClass {
padding: 0.4em;
margin: 0.3em; /* Yes! */
}
Fourth
It may be better to merge ideas from the First and Third by adding some global variables and doing this:
LESS
@unit:em;
@basevalue:1;
@val: 1;
@setUnit: unit(@basevalue*@val, @unit);
.someAwesomeClass {
& {
@val: .2;
padding: @setUnit;
}
& {
@val: .1;
margin: @setUnit;
}
}
CSS Output
.someAwesomeClass {
padding: 0.2em;
margin: 0.1em;
}
So here we are using the unit
function still as the First idea, but have assigned it to the variable @setUnit
, so each time the variable is called, it runs the function. We still isolate our property blocks using the & {}
syntax like in the Third solution, but now we just set the @val
to what we want and call the @setUnit
where we want.
Calculate just a value in less
In short, no, you can't define "true" functions in Less. So for the particular use-case the most compact approach is something like this:
@context: 16px;
@u: 1em / @context;
.body {
font-size: 22 * @u;
padding: 0 10 * @u;
}
Or this:
@context: 16px;
@u: 1em / @context;
.body {
font-size: @u * 22px;
padding: 0 @u * 10px;
}
whichever you find more readable (note that arithmetic expressions require parens if you use --strict-math=on
option).
LESSCSS: Assign a value to a property taken from another one's
This is possible starting with v3 of LESS! Here is the documentation on it.
The example use case they provide ends up with the background-color getting the same value as the color property when compiled:
.widget {
color: #efefef;
background-color: $color;
}
Less CSS - How to return value in viewport with (vw)
The best way to achieve the expected output would be to multiply the value by 100vw. This would be the most meaningful and easily understandable method.
a{
width: 700/1400 * 100vw;
}
The below method of using unit()
function works too but I wouldn't really recommend it.
One of the primary reasons why I wouldn't recommend it is because I am not sure if that is supposed to work as it does. The .unit()
function is supposed to take a number as its first parameter and add the units to it but a percentage value is not exactly a number and this may not work in future versions depending on how the Less core team view it
I read the docs and it seems like the first parameter can be a number with or without a dimension but I still wouldn't recommend it because the earlier method is far more easier to understand than the usage of functions.
b{
width: unit(percentage(700/1400), vw);
}
How to get value in percentage (%) or pixel (px) after doing some maths? | Lesscss
use:
unit(@yourvalue,px)
or
unit(@yourvalue,~"%")
read more here
Additional note:
by default the first occurring unit in the calculation will be assigned to the result. For example unit((1 / 2 * 3),px);
and (1px / 2% * 3rem)
will both return 1.5px
.
Is there a way to use variables in Less for the ~ operator, like ~calc(100% - @spacing);
To disable the calculation which LESS does automatically when discovering a -
between two numeric values but still being able to use variables, you can write one of the following:
1) Only escape the operator that triggers the calculation and use the variable like you normally do
@padding: 20px;
body {
padding: calc(100% ~"-" @padding);
}
2) Escape the whole expression and interpolate the variable with the @{padding}
notation
@padding: 20px;
body {
padding: ~"calc(100% - @{padding})";
}
I prefer the second version, since it resembles javascript's template literals and looks a bit cleaner, but either way works just fine.
Both solutions disable the automatic Less calculation and compile to the correct result:
body {
padding: calc(100% - 20px);
}
How to calculate percentages in LESS CSS?
According to the LESS CSS website, you need to change the order of your equation
The output is pretty much what you expect—LESS understands the difference between colors and units. If a unit is used in an operation, like in:
@var: 1px + 5;
LESS will use that unit for the final output—
6px
in this case.
It should be:
width: 100%*(140/620);
Can numbers be rounded (math term) using LESS CSS?
Yes they can:
line-height: ceil(@height * .666); // 20px (round up)
line-height: floor(@height * .666); // 19px (round down)
line-height: round(@height * .666); // 20px (round to closest integer)
line-height: round(@height * .666, 1); // 20.0px (round to 1 decimal place)
LESS CSS Functions: Utilize Different Values
You could use the &
selector and just put it there twice. This pulls the mixins into 2 different scopes and keeps them from conflicting with one another. It's a bit hacky and not the cleanest looking thing but it does work, like so:
div {
&{
.emSpacing(16);
margin-top: @emSpacing;
}
&{
.emSpacing(32);
margin-bottom: @emSpacing;
}
}
This allows you to use the mixin twice with 2 different values using the same as the parent's selector. You'd then group all the properties you want to use that value into the same block.
You could clean up the look of single line uses a bit by doing something like:
div {
&{.emSpacing(16); margin-top: @emSpacing;}
&{.emSpacing(32); margin-bottom: @emSpacing;}
}
Still don't think it's super clean though it doesn't seem there's an alternative.
Edit
Looks like there's a plugin that would give you the format you want.
Less Plugin Functions
Instructions on use are in the readme.
Related Topics
Disable/Turn Off Inherited CSS3 Transitions
Why Does "Left: 50%, Transform: Translatex(-50%)" Horizontally Center an Element
Google Chrome "Failed Parsing Sourcemap":Css.Map (Web Essential)
Twitter Bootstrap - Fixed Layout with Scrollable Sidebar
Web Testing for Ie. How Accurate Is Ietester
How to Get a Three Column Layout with Twitter Bootstrap
Is There Any Guide on "When to Use Display:Block When :Inline and When :Inline-Block" and Why
Differencebetween Bootstrap.CSS and Bootstrap-Theme.Css
Google Chrome Showing Black Border on Focus State for Button User Agent Styles
Why Use * Selector in Combination with *::Before and *::After
Dynamically Generate CSS File from Database in ASP.NET MVC
CSS H1 - Only as Wide as the Text
Dynamically Change CSS Style of Cell in <H:Datatable> Column
The Scrolling Attribute on the Iframe Element Is Obsolete. Use CSS Instead
Flexslider Border-Radius Does Not Wrap Image in Chrome, Safari, But Will in Firefox