Less mixin variable call mixin - less

I have this very simple example as you can see:
.large{
color: blue;
}
.a(#va){
.large;
~".#{va}()";
}
a{
.a(large)
}
I keep trying to get the .large() or .large; to work by calling the .large mixin. I keep getting error:
Parse error: Unrecognised input
.large; ~".#{va}()";}
How can I fix this?

You can't call a mixin by its name stored in a variable. You can achieve the goal by wrapping mixin call into "detached ruleset" though, e.g.:
.large {
color: blue;
}
.a(#va) {
#va();
}
a {
.a({.large})
}
There're other methods of doing similar things (might be more useful/suitable depending on a use-case).

Related

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.

Less mixin and variables

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;
}

Use a mixin named parameter in LESS as a pseudo selector

My idea here is to create a LESS mixin that could add a pseudo element :before or :after to any element in my page.
I have tried to use the "Named parameter" of LESS mixins to create a generic mixin in which the user could specify whether the pseudo element should be a :before or an :after.
When I compile, I get an error: "Unrecognized input".
Here is my code:
.setInlineIcon(#iconx: 0; #icony: 0; #pos: before; #margin: 0; #margindir: right) {
&:#{pos} {
.setStructure(#h: 16px; #w: 16px; #d: inline-block; #va: middle);
.getIcon(#iconx; #icony);
content:"";
margin-#{margindir}: #margin;
}
}
Where .setStrucutreand .getIcon are two already existing and functioning mixins. Can you spot what's wrong?
Is it because I cannot use a variable as a selector in this way?
: alone is not recognized as valid selector identifier. The workaround is to concatenate it to the identifier before selector interpolation:
.mixin(#pos) {
#name: ~':#{pos}';
&#{name} {
/* ... */
}
}
usage {
.mixin(before);
}

LESS CSS: selector substitution?

This is an existing general css rule (original file):
.caption-top {
color: red;
}
This is schematic, because in real life case, I need the .caption-top selector to become something else, depending on the context. But I would like to use a variable instead of changing the all occurrences of the selector. For example, in one context, it should become .field-name-field-caption-top. So I did this (wrapper file):
#caption-top: .field-name-field-caption-top;
#caption-top {
color: red;
}
This generates a LESS parse error. Is there another method to establish a rule to substitute a selector? So that, for the above example, the rule will finally look like this:
.field-name-field-caption-top {
color: red;
}
Additional info
The whole point is to not touch the original css file, because it comes from outside and will be overwritten, but instead, to wrap it and tell Less how to replace existing classes with classes used in a particular theme. If it is not possible to achieve, then acceptable solution will be to change the original file in an automatic way, like e.g. replace all occurrences of ".caption" with "#caption" (which I suggested in the above code sample) or make an import at the beginning etc. Then use a wrapper Less file (aware of the theme implementation) to specify what classes whould be replaced with what.
You can use escaping to achieve this:
#selector: '.myclass';
(~'#{selector}') {
color: red;
}
However you cannot do this:
(~'#{selector}') .another {
color: red;
}
To achieve the above you will need to alter the variable
#selector: '.myclass .another';
You need to produce a function of two arguments that generates the desired CSS:
.generator(#fieldName, #fieldCaption) {
.#{fieldName}-#{fieldCaption}-top {
color: red;
}
}
.generator(foo, bar);
(Feel free to try this in the online less compiler)
This piece of code produces the desired CSS for elements with name "foo" and caption "bar". You just need to make more calls to the .generator function with different arguments to obtain what you need.
If this does not correspond to what you need, please provide one additional example of your desired CSS output.
It looks like mixins are what you need:
.caption-top {
color: red;
}
.field-name-field-caption-top {
.caption-top
}
You can define a class that, used or not, you can then reference again and again inside other selectors. You can even combine them with new styles, thereby extending what the original block of CSS would have done:
.field-name-field-caption-bottom {
font-size: 3em;
.caption-top
}
Give it a go in the compiler!