Understanding Less Guards and Loops

The developers’ desire to bring features from programming to CSS led to creation of CSS preprocessors. They allow us to define variables and create functions just as we do so in JavaScript; but even more important, we can make our code more flexible by using conditional and iterating blocks.

Such blocks can be created using Less, but the syntax for their use is quite different from the traditional if..else and for patterns. In contrast to Sass and Stylus, Less tries to stick as close as it can to the original CSS. Therefore, to construct conditionals and loops, it uses syntax borrowed from media queries. This can be a bit confusing at first, but once we learn how it works, we will see that it’s just another way to say the same thing.

Less Mixin Guards

Less calls its conditional statements mixin guards. To construct a conditional block, we need to use mixins in conjunction with guards. Let’s demonstrate the main scheme with an example:

Here, we have a mixin with one parameter .theme(@mode). We check if that parameter matches with a specific condition. Only once the parameter passes the test will the code inside the mixin be executed. For each separate condition, we need to repeat the name of the mixin along with its parameter(s). In our case, we have two conditions. As we can see, to substitute the if keyword, used in many other programming languages, Less uses guards. A guard is created by the when keyword followed by a specific condition. To understand it more easily let’s see how the above block would looks like in JavaScript:

Cool! But what if we have a shared style, which we want to apply in both cases. For example, when the theme is set to “light”, along with the light blue background color, we want to add an orange border too. To do so, we need to add a mixin without a guard, after our conditions:

OK. Let’s take a look at another slightly different variant. This time we want to add a default style, which will be applied when neither the first condition, nor the second one is met. To do so, we add a mixin with a special type of guard – instead of a regular condition we use the default() function.

Here, we use the OR operator too, which in Less is emulated by a comma. The code for this guard have exactly the same effect as the default() function.

Less Loops

Less defines a loop in a similar way to mixin guards. First, we create a mixin with a counter parameter, and a guard with our condition. Then, we put the code, which we want to be generated, inside the mixin. The last thing we need is a way to increment/decrement the counter value. We use the fact that a mixin can call itself and we add the same mixin as nested function. As an effect of this, our mixin will loop and iterate as long as the condition set in the guard is matched. Let’s make things clearer with the following example:

We have a counter parameter set to 1 (@i:1) and a condition (@i =) which will return true until the counter value is equal or lesser than 3. Inside the mixin, we put the code we want to be generated on each iteration. And finally, to make the iteration possible, we add the mixin itself as a nested function, which will increment the counter value by one (@i + 1).

The above code block is similar to the following for loop in JavaScript:

for (i = 1; i <=3 ; i++) {
...
}

When the code is compiled, the style block from the mixin is repeated three times as expected, and thus three different classes are output:

Note that the place where you put the increment function matters. If you put it above the styles then the order in compiled code will be reversed – .variant-3 will be output first, and so on.

Summary

As we can see, Less’ variants of if..else and for blocks aren’t so confusing as they may look at first glance. Once we grasp how they work, we can easily use them to make our CSS more flexible and reusable.

Ivaylo Gerchev is a self-taught web developer/designer. He loves to play with HTML, CSS, jQuery, PHP, and WordPress, as well as Photoshop and Illustrator. Ivaylo's motto is "Minimum effort for maximum effect!"