Less mixin and variables - less

I have the following mixin:
.iconFont(#color: #green, #font-size: 18px){
color: #color;
font-size: #font-size;
}
If I want only to change the second variable value, I need to write the first variable default value?
h1{
.iconFont(#green, 14px);
}

No, there is no need to specify the default value for the first parameter while calling the function. Instead you can just use named parameters feature to explicitly let the compiler know that the value you are passing in the mixin call is for the 2nd parameter.
.sample{
.iconFont(#font-size:14px);
}
The above Less code when compiled would produce the below output. (Note: I had set the #green as #00ff00.)
.sample {
color: #00ff00;
font-size: 14px;
}
While using the named parameter feature, even the order in which the parameters are passed does not matter. For example, the same mixin can be called as follows:
.sample2{
.iconFont(#font-size:24px, #color: #070707);
}
And it would produce the below as output.
.sample2 {
color: #070707;
font-size: 24px;
}

Related

How to use the default variable for only one of a few variables in less

Here is my mixin
.test(#color:black; #width:100px; #height:50px) {
width:#width;
height:#height;
background:#color;
}
Here is where it's called later
.mydiv {.test('use-mixin-color'; 300px; 150px);}
How can I override the size of .mydiv, while using the color defined in the mixin?
Everything I have tried overrides the mixin color.
To Use mixin in LESS, pass those parameter to override mixin default value :
Soluations :
.test(#color:black; #width:100px; #height:50px) {
width : #width;
height : #height;
background : #color;
}
.mydiv {
.test(#width : 300px; #height : 150px);
}
OUTPUT :
.mydiv {
width: 300px;
height: 150px;
background: black;
}
Helpful :)
In addition to the accepted answer. There're multiple methods (actually infinite) but if you want your mixin to be most easy for use you can provide a "specialization" for a specific argument value or number of arguments. Like this for example:
// usage:
.foo {.test(red, 1px, 2px)}
.bar {.test(3px, 4px)}
// impl.:
.test(#color, #width, #height) {
width: #width;
height: #height;
background: #color;
}
.test(#width, #height) { // <- "no color" specialization
.test(black, #width, #height);
}
Demo.
Also think twice before adding default parameter values for a mixin like:
.test(#color: black, #width: 100px, #height: 50px) { ...
People tend to overuse this feature while it's rarely really necessary (and only creates an extra code-noise) except some specific use-cases.
I.e. consider if you actually expect your mixin to be invoked as:
test;
test(blue, 4em);
// etc.
Do you?
It's usually a good idea to start without default parameter values (at least to protect the mixin against accidental misuse), i.e.:
.test(#color, #width, #height) { ...
and add them later only where and when they are necessary.

Can whole declaration be stored as #variable value in Less?

All my Less variables are editable within a CMS-module and are assigned to the Less compiler. It works, if I only use the values like color, font-size, etc.:
body {
background-color: #bgColor;
}
I've created another field for custom Less, which I would like to add at the end of my Less file, like:
body {
background-color: #bgColor;
}
#customLess /* desired OUTPUT: body { color: white; }*/
Unfortunately this leads to an ParseError.
I'd like to avoid to merge the existing Less and custom Less. I'm not looking for mixins, I guess.
Is it possible to put whole declarations in a #variable?
It is very much possible to put whole declarations (including the selector, property + value pair) inside a variable. Those are called as detached rulesets.
While calling them, braces (()) must be added. If not, the call will fail and result in compilation error. Below is an extract from the official website.
Parentheses after a detached ruleset call are mandatory. The call #detached-ruleset; would NOT work.
#customLess: {
body{
color: white;
}
};
#bgColor: red;
body {
background-color: #bgColor;
}
#customLess();

Overriding mixins in LESS

when defining a mixin multiple times in LESS, and later calling that mixin as follows
.background-color() {
background: red;
}
.background-color() {
background: yellow;
}
body {
.background-color;
}
the result will be a combined output from all the defined mixins
body {
background: red; // << output from mixin #1
background: yellow; // << output from mixin #2
}
while when you apply the same scenario in both Sass & Stylus ( using their own syntax of course ), when you call a mixin that is defined multiple times across your stylesheets, Only the last defined one will be executed ( it will override all previously defined mixins ) as follows.
result Sass and Stylus
body {
background: yellow; // << output from mixin #2
}
how can I override a mixin in LESS so that the output will be from the last defined mixin ?
You can not override them, alternatively use a variable to define the 'background-color'. For Less variables the last declared win.
Also read Pattern-matching
In Less all matching mixins are compiled in the source. You can use namespace to prevent name collisions, for instance:
#ns1 {
.background-color() {
background: red;
}
}
#ns2 {
.background-color() {
background: yellow;
}
}
than you can use:
body {
#ns2 > .background-color;
}
Double properties are also not removed to make some browser hacks possible, example:
#myElement {
width: 300px;
width: 500px\9;
}
To find a solution for your use case you should reformulate your question and explain why you have these same named mixins in the first place.

Validity of .LESS code

I got a .less file and it has codes written in this fashion:
.btn-form{
.button-toggle( #brand-black; #brand-white; #btnform-color; #btnform-hover-color; #border-color);
}
What does this code mean?
In your example, .button-toggle is a mixin, declared elsewhere in your code (possibly an imported Less file). The declaration might be something like:
.button-toggle(#brand-black; #brand-white; #btnform-color; #btnform-hover-color; #border-color) {
background: #btnform-color;
color: #brand-black;
&:hover {
background: #btnform-hover-color;
color: #brand-white;
}
border-color: #border-color;
// other CSS properties or nested selectors
}
It receives as parameters several variables, which should also be declared somewhere before you call the mixin, like:
#brand-black: black;
#brand-white: #fff;
#btnform-color: blue;
#btnform-hover-color: red;
#border-color: rgb(255,255,0);
You are calling the mixin when you place it inside a block, as you did, and it will generate CSS according to its definition and the parameters you are passing.
For example, if you call your code block preceded by those variable declarations and the mixin declaration I included above in a LESS compiler such as the online service http://lesstester.com/ you will get this CSS result:
.btn-form {
background: #0000ff;
color: #000000;
border-color: #ffff00;
}
.btn-form:hover {
background: #ff0000;
color: #ffffff;
}

Change variable used in mixin depending on scope

In the Lazy Loading section of the Less language features, it states:
When defining a variable twice, the last definition of the variable is used, searching from the current scope upwards. This is similar to css itself where the last property inside a definition is used to determine the value.
I'd like to overwrite a global variable, but this doesn't seem to work:
#border: #fff;
.table {
border: #border;
}
.table-summary {
#border: #000;
.table
}
Compiles to
.table {
border: #ffffff;
}
.table-summary {
border: #ffffff; // I want this to be #000
}
Currently the global scope has higher precedence than caller scope for a mixin (unless the mixin is defined inside parametric namespace). For more more details see #1316, some people consider this is a bug but there's no well-defined agreement on that.
Either way, the recommendation is to minimize use of non-parametric mixins and to not rely on indirect parameter passing whenever possible. Your example is a perfect use-case for a parametric mixin (even if your the code becomes slightly more verbose):
#border-default: #fff;
.table-base(#border: #border-default) {
border: #border;
}
.table {
.table-base;
}
.table-summary {
.table-base(#000);
}
Alt. if for some reason you can't modify the .table class (for example if it's defined in an external library) then just forget about any variables and override the property directly, the most optimal way would be:
#border: #fff;
.table {
border: #border;
}
.table-summary:extend(.table) {
border-color: #000;
}
---
Technically, there's method to achieve what you want with the code quite close to your original snippet but I doubt it is something to be really recommended:
#border: #fff;
.table {
border: #border;
}
.-;.-() { // dummy parametric namespace
.table-summary {
#border: #000;
.table;
}
} // end of dummy parametric namespace