I am trying to generate a number of classes in a loop based on a number of pre-defined variable snippets.
I have a variables.less document that I am importing at the top of this less file containing my color variables. I then want to generate matching classes for these, but I am unable to get less to compile the variable.
My code:
.loop-class(~"primary", ~"success", ~"info", ~"warning", ~"danger";);
.loop-class(@list, @index: 1) when (isstring(extract(@list, @index))) {
@status: extract(@list, @index);
.button-@{status} {
color: ~'@button-@{status}';
}
.loop-class(@list, (@index + 1));
}
Which compiles to:
.button-primary {
color: @button-primary;
}
.button-success {
color: @button-success;
}
etc etc
As you can see, I get the variable name to concatenate correctly, but I can not get it to resolve, so I'm guessing that LESS has already done it's variable compilation before getting to this function?
I have already tried moving the variables into this document, as well as wrapping the variables in a mixin and adding that inside the .loop-class, but neither of these seemed to help.
I also tried something like:
@status: extract(@list, @index);
@compileClass: ~'@button-@{status}';
.button-@{status} {
color: @compileClass;
}
where I am saving the variable in a another one and then referencing that, but it yields the same result.
I looked at less css calling dynamic variables from a loop and tried implementing that as follows:
.loop-class(~"primary", ~"success", ~"info", ~"warning", ~"danger";);
.define(@var) {
@fallback: ~'@button-@{var}';
}
.loop-class(@list, @index: 1) when (isstring(extract(@list, @index))) {
@status: extract(@list, @index);
.button-@{status} {
.define(@status);
color: @@fallback;
}
.loop-class(@list, (@index + 1));
}
But that gave me the error that @@button-danger (last in the index) is undefined, so it still can't resolve the variable.
Is it obvious to you guys what I'm doing wrong?
Thanks for your help!
You are missing a set of needed brackets to resolve the variable:
LESS
//imported from another file
@button-primary: cyan;
@button-success: green;
@button-info: orange;
@button-warning: yellow;
@button-danger: red;
//in your mixin file
.loop-class(~"primary", ~"success", ~"info", ~"warning", ~"danger";);
.loop-class(@list, @index: 1) when (isstring(extract(@list, @index))) {
@status: extract(@list, @index);
.button-@{status} {
color: ~'@{button-@{status}}'; /* two more brackets needed */
| |
here here
}
.loop-class(@list, (@index + 1));
}
CSS Output
.button-primary {
color: #00ffff;
}
.button-success {
color: #008000;
}
.button-info {
color: #ffa500;
}
.button-warning {
color: #ffff00;
}
.button-danger {
color: #ff0000;
}
Also, as a matter of less cluttered and more user friendly code, you can remove your multiple string interpolations needed for the mixing call by changing isstring
to iskeyword
in your mixin:
.loop-class(primary, success, info, warning, danger;); /* cleaner code on call */
.loop-class(@list, @index: 1) when (iskeyword(extract(@list, @index))) {
@status: extract(@list, @index);
.button-@{status} {
color: ~'@{button-@{status}}';
}
.loop-class(@list, (@index + 1));
}