In Less, is it possible to access part of a class name and use within a mixin?
This will be best explained with an example:
I have a grid which i have declared as follows:
.columns (@columns) {
//code here to generate column widths
}
//This is where my problem is:
.column-1 {
.col (1)
}
.column-2 {
.col (2)
}
.column-3 {
.col (3)
}
// etc etc
Obviously there is a lot of repetitive code going on here. Ideally i would like to be able to not have to declare column-1 column-2 etc and have some way, regex perhaps, of parsing the class name, and using the value after the dash to automatically calculate the column width. I am almost certain twitter bootstrap is doing something similar but i cant understand it:
.spanX (@index) when (@index > 0) {
(~".span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
I think you'll understand that :
.columnX (@index) when (@index > 0) { // Guarded mixin: use this mixin when the condition is true (like an if statement)
(~".column-@{index}") { // outputs .column-0 as a class name
.col(@index); // for the contents, use the col mixin
} // which class you are doing
.columnX(@index - 1); // Recursive call to the same mixin, going down by 1
}
.columnX (0) {} // Default implementation so that when .columnX(0) is called, a matching mixin is found.
.col (@index) {
// actual css that will be applied to column-1 if @index is 1
width: @index * 10px; // for example
}
.columnX(3); // number of columns you want
Edit (missed the ;
of .columnX(3);
) Edit Added more comments
All this should give the result :
.column-3 {
width: 30px;
}
.column-2 {
width: 20px;
}
.column-1 {
width: 10px;
}
This is essentially the same as @sherbrow's answer, but a little more concise and doesn't error. Consider this a long explanatory comment to support his correct answer - it's just a lot more than fits in a comment!
You'll use a LESS loop mixin like this as an intermediate helper, and then call it specifying the number of classes you want to generate. Here's how to do .column-1
, .column-2
, and .column-3
. If say you wanted to go up to four columns: just do .columns(4)
instead of .columns(3)
[line 9]. To go up to five columns, just do .columns(5)
.
1 // we'll call this if we want to build columns
2 .columns(@i) when (@i > 0) {
3 .column-@{i} {
4 .col(@i)
5 }
6 .columns(@i - 1)
7 }
8 // for example, here we build columns 1-3
9 .columns(3);
which will compile to the result of
.column-1 {.col(1)}
.column-2 {.col(2)}
.column-3 {.col(3)}
(Your question assumes there's already a mixin .col(@x)
so I'm assuming that too. See 4 for how to skip that extra step.)
Here's what's happening:
.columns(3)
[line 9] sends us to the .columns(@i)
mixin [line 2], assigning the variable @i
the value 3
. @i
(3) is greater than 0 [line 2], we satisfy the guard and are allowed past the {
[line 2]. .column-@{i} {...}
[lines 3-5] is what this mixin will output.
@i
is 3, so the output will be .column-3 {.col(3)}
@{i}
is used to insert the variable's value as a string .col(@x)
anywhere else, you could also just drop styles in here directly, eg (a là @sherbrow) .column-@{i} {width: @i * 10px}
.columns(@i - 1)
==> .columns(3 - 1)
==> .columns(2)
. @i
, now 2, is greater than zero, so we're allowed in. output .column-2 {.col(2)}
(where .col(2)
is immediately compiled, so your compiled CSS actually reads .column-2 { the.col(2)styles }
) @i
isn't greater than 0 (ie stop after .columns(1)
).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.