Lists and loops
Less has no @for and @each like Sass. Repetition is done in two ways: with a recursive mixin that calls itself, and with the each() function. Loops are needed to get dozens of utility classes from one list of values.
Lists
A list is values separated by commas or spaces in one variable. There are functions for working with it (the examples use @list: 4px, 8px, 16px):
| Function | What it returns | Example | Result |
|---|---|---|---|
length() | The number of items | length(@list) | 3 |
extract() | An item by its number, counting from 1 | extract(@list, 2) | 8px |
range() | A list of numbers | range(4) | 1 2 3 4 |
// styles/main.less
@sizes: 12px, 16px, 20px;
.text-small {
font-size: extract(@sizes, 1);
}
.text-large {
font-size: extract(@sizes, length(@sizes));
}.text-small {
font-size: 12px;
}
.text-large {
font-size: 20px;
}A recursive mixin
A mixin with a guard calls itself with a smaller number while the condition is true. This is how grid columns are created:
// styles/main.less
.make-columns(@i) when (@i > 0) {
.col-@{i} {
width: percentage((@i / 4));
}
.make-columns(@i - 1);
}
.make-columns(4);.col-4 {
width: 100%;
}
.col-3 {
width: 75%;
}
.col-2 {
width: 50%;
}
.col-1 {
width: 25%;
}The call .make-columns(4) output .col-4, then called .make-columns(3) and so on down to zero, where the condition @i > 0 is false and the recursion stopped.
The each function
each() is simpler: it walks through a list and runs a ruleset for every item. Inside you have @value — the value, @key — the key, and @index — the number from 1:
// styles/main.less
@spacers: 4px, 8px, 16px;
each(@spacers, {
.mt-@{index} {
margin-top: @value;
}
});.mt-1 {
margin-top: 4px;
}
.mt-2 {
margin-top: 8px;
}
.mt-3 {
margin-top: 16px;
}Looping over a map
With a map each() gives you the key and the value — handy for colour classes:
// styles/main.less
@colors: {
primary: #2563eb;
success: #16a34a;
danger: #dc2626;
}
each(@colors, {
.text-@{key} {
color: @value;
}
});.text-primary {
color: #2563eb;
}
.text-success {
color: #16a34a;
}
.text-danger {
color: #dc2626;
}<style>
.text-primary {
color: #2563eb;
}
.text-success {
color: #16a34a;
}
.text-danger {
color: #dc2626;
}
</style>
<p class="text-primary">A new post</p>
<p class="text-success">The post is published</p>
<p class="text-danger">Saving failed</p>Common mistake
A recursive mixin without a guard or without decreasing the counter never stops:
// styles/main.less
.make-columns(@i) {
.col-@{i} {
width: percentage((@i / 4));
}
.make-columns(@i - 1);
}
.make-columns(4);Less goes into endless recursion, and compilation fails with the unclear error SyntaxError: undefined on the line of the call. Always write when (@i > 0) and call the mixin with @i - 1.