I am trying to create a mixin that dynamically defines variables in LESS CSS, by actually assigning them a composite name.
The simplified use-case (not the real one)
I`m not really sure for what you want to use this, but one of my suggestion is based on @ScottS answer. On my real world, I need to create a web app, where it would show several brands and each brand have their own text color, background and so on... so I started to chase a way to accomplish this in LESS, what I could easily do on SASS and the result is below:
// Code from Seven Phase Max
// ............................................................
// .for
.for(@i, @n) {.-each(@i)}
.for(@n) when (isnumber(@n)) {.for(1, @n)}
.for(@i, @n) when not (@i = @n) {
.for((@i + (@n - @i) / abs(@n - @i)), @n);
}
// ............................................................
// .for-each
.for(@array) when (default()) {.for-impl_(length(@array))}
.for-impl_(@i) when (@i > 1) {.for-impl_((@i - 1))}
.for-impl_(@i) {.-each(extract(@array, @i))}
// Brands
@dodge : "dodge";
@ford : "ford";
@chev : "chev";
// Colors
@dodge-color : "#fff";
@ford-color : "#000";
@chev-color : "#ff0";
// Setting variables and escaping than
@brands: ~"dodge" ~"ford" ~"chev";
// Define our variable
.define(@var) {
@brand-color: '@{var}-color';
}
// Starting the mixin
.color() {
// Generating the loop to each brand
.for(@brands); .-each(@name) {
// After loop happens, it checks what brand is being called
.define(@name);
// When the brand is found, match the selector and color
.brand-@{name} & {
color: @@brand-color;
}
}
}
.carColor {
.color();
}
Te result will be:
.brand-dodge .carColor {
color: "#fff";
}
.brand-ford .carColor {
color: "#000";
}
.brand-chev .carColor {
color: "#ff0";
}
This is very tricky and I had to use several elements to get what I needed, first used a set of mixins provided by Seven Phase Max and you can find it here and than, the @ScottS answer was the piece that was missing fro my puzzle... hope this helps you and others that need to create a set of Variables to be part of another variable and create a more dynamic less file.
You can copy my entire code and test at http://lesstester.com/
To follow up on the accepted answer you can also define a value for the variable by extending the .define() mixin as follows. This allows you to use a temporary set of variables within a rule.
.define(@var, @val) {
.foo() when (@var = temp1) {
@temp1: @val;
}
.foo() when (@var = temp2) {
@temp2: @val;
}
.foo() when (@var = temp3) {
@temp3: @val;
}
.foo();
}
.define(temp2, 2);
.test {
.define(temp1, 0);
prop: @temp1;
}
.test2 {
prop: @temp2;
}
.test {
prop: 0;
}
.test2 {
prop: 2;
}
Here is a more complicated gist of how I use this in a mixin for generating responsive background images with background-size: cover; (and an IE8 fallback).
I don’t have time to build out the examples, but none of the above are as quick and simple as defining a variable and then assembling the import based on it. Then just have multiple documents where the same variables are defined.
@whitelabel: 'foo';
@import 'whitelabel/@{whitelabel}/colors';
What you desire to do is not currently possible in LESS. I can think of two possible "workarounds" if you know ahead of time what variable names you want to allow to be used (in other words, not fully dynamic). Then something like one of the following could be done:
.define(@var) {
@fooBar: 0;
@fooTwo: 2;
@fooYep: 4;
@fooSet: 'foo@{var}';
}
.define(Two);
.test {
.define(Bar);
prop: @@fooSet;
}
.test2 {
prop: @@fooSet;
}
LESS
.define(@var) {
.foo() when (@var = Bar) {
@fooBar: 0;
}
.foo() when (@var = Two) {
@fooTwo: 2;
}
.foo() when (@var = Yep) {
@fooYep: 4;
}
.foo();
}
.define(Two);
.test {
.define(Bar);
prop: @fooBar;
}
.test2 {
prop: @fooTwo;
}
.test {
prop: 0;
}
.test2 {
prop: 2;
}
But I'm not sure how useful either would really be, nor do I know if it could have any real application in your actual use case (since you mention the above is not the real use case). If you want a fully dynamic variable in LESS, then it cannot be done through LESS itself.