Reputation: 21003
I am using the following code to generate a column layout using LESS CSS:
.columnBuilder (@index) when (@index =< @columnCount) {
.container_@{columnCount} .grid_@{index} {
width: unit(((@baseWidth / @columnCount) * @index)-10, px);
}
.columnBuilder(@index + 1);
}
Which gives me an output:
.container_24 .grid_1 {
width: 69px;
}
.container_24 .grid_2 {
width: 148px;
}
.container_24 .grid_3 {
width: 227px;
}
etc...
How would i now create a new less function that would give an output of:
.grid_1,
.grid_2,
....,
.grid_N {
display: inline;
float: left;
margin-left: 5px;
margin-right: 5px;
}
Where N
is defined as @columnCount: 24;
, though the column count is not set, it can be changed to any number. I am aware i could create a body for each grid_X
would like to avoid it to keep clutter down.
Upvotes: 3
Views: 1539
Reputation: 72261
:extend()
in LESS 1.4+This seems to accomplish it more elegantly. You first define the initial values you will want extended in a hard coded .grid_1
class (at present, LESS will not extend dynamically generated classes), then add an extender mixin in your loop to extend to that class. Like so:
.grid_1 { //this acts as the "launch point" for extending them all
display: inline;
float: left;
margin-left: 5px;
margin-right: 5px;
}
.columnBuilder (@index) when (@index =< @columnCount) {
//we are going to use this class twice, so just calculate it once
@gridClass: ~'.grid_@{index}';
//this is your original code except the variable now used for the grid class
.container_@{columnCount} @{gridClass} {
width: unit(((@baseWidth / @columnCount) * @index)-10, px);
}
//this is your extender feature, which does not do so for the initial .grid_1
//which was set above as our launch point.
@{gridClass} {
.extender() when (@index > 1) {
&:extend(.grid_1 all);
}
.extender() when (@index = 1) {}
.extender();
}
//iterate the loop just as you were doing
.columnBuilder(@index + 1);
}
//call the loop starting at 1
.columnBuilder(1);
Output is your expected:
.grid_1,
.grid_2,
....,
.grid_N {
display: inline;
float: left;
margin-left: 5px;
margin-right: 5px;
}
Upvotes: 5
Reputation: 21003
As it turns out, LESS has no native support for something like this and will always create multiple blocks of CSS each with its own body, so you need to run a little hack with mixins. I used the following:
.columnBuilderX (@index) when (@index = 1) {
@isel: ~".grid_@{index}, ";
.columnBuilderX (@index + 1, @isel);
}
.columnBuilderX (@index, @innerSel) when (@index =< (@columnCount - 1)) {
@isel: @innerSel + ~".grid_@{index}, ";
.columnBuilderX (@index + 1, @isel);
}
.columnBuilderX (@index, @innerSel) when (@index = @columnCount) {
@isel: @innerSel + ~".grid_@{index} ";
@{isel} {
display: inline;
float: left;
margin-left: 5px;
margin-right: 5px;
}
.columnBuilderX (@index + 1, @isel);
}
Which produced for me:
.grid_1, .grid_2, .grid_3, .grid_4, .grid_5, .grid_6, .grid_7, .grid_8, .grid_9, .grid_10, .grid_11, .grid_12, .grid_13, .grid_14, .grid_15, .grid_16, .grid_17, .grid_18, .grid_19, .grid_20, .grid_21, .grid_22, .grid_23, .grid_24 {
display: inline;
float: left;
margin-left: 5px;
margin-right: 5px;
}
The first mixin is the initial mixin that is called that does not already have an inner selector, the second mixin requires a second param, which is the variable we create in the first, which then runs recursively until we hit our last column as defined by the when
clause, where we add our last selector without the comma, and then use the selector list we have built in to apply our CSS too.
If anybody can come up with something simpler than this, please create an answer.
Upvotes: 0