Understanding Less Guards and Loops

Share this article

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:

.theme (@mode) when (@mode = "dark") {
  background-color: darkblue;
}
.theme (@mode) when (@mode = "light") {
  background-color: lightblue;
}

div {
  width: 50px;
  height: 50px;
  .theme("light");
}

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:

function theme(mode){
  if (mode == "dark"){
   element.style.backgroundColor = "darkblue";
 } else if (mode == "light"){
   element.style.backgroundColor = "lightblue";
  }
}

So, a mixin guard is just a function with nested if..else statement(s). Although it’s created in a different manner.

In our div example, we use the mixin guard with “light” passed as parameter – .theme("light"). And when the code is compiled by Less, we get the following output:

div {
  width: 50px;
  height: 50px;
  background-color: lightblue;
}

See the Pen Less Guards and Loops Example 1 by SitePoint (@SitePoint) on CodePen.

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:

.theme (@mode) when (@mode = "dark") {
  background-color: darkblue;
}
.theme (@mode) when (@mode = "light") {
  background-color: lightblue;
}
.theme (@mode) {
  border: thick solid orange;
}

div {
  width: 50px;
  height: 50px;
  .theme("light");
}

Now, we can see that the style from the last block of our mixin guard is added in the compiled code:

div {
  width: 50px;
  height: 50px;
  background-color: lightblue;
  border: thick solid orange;
}

If we change the theme’s mode to “dark”, the style for the border will still remains.

See the Pen Less Guards and Loops Example 2 by SitePoint (@SitePoint) on CodePen.

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.

.theme (@mode) when (@mode = "dark") {
  background-color: darkblue;
}
.theme (@mode) when (@mode = "light") {
  background-color: lightblue;
}
.theme (@mode) when (default()) {
  background-color: @mode;
}

div {
  width: 50px;
  height: 50px;
  .theme(red);
}

This variant is equivalent to the final else in an JavaScript’s if..else block:

function theme(mode){
  if (mode == "dark"){
   element.style.backgroundColor = "darkblue";
 } else if (mode == "light"){
   element.style.backgroundColor = "lightblue";
  } else {
   element.style.border = mode;
  }
}

We use red as parameter and it doesn’t match neither with “light” nor with “dark”. Therefore, the background color is set to red in the compiled code:

div {
  width: 50px;
  height: 50px;
  background-color: red;
}

See the Pen Less Guards and Loops Example 3 by SitePoint (@SitePoint) on CodePen.

Less also allows us to use logical operators with guards. So, if we need to negate a condition, we can do so by using the not keyword, like so:

.theme(@mode) when not (@mode = "dark"), (@mode = "light")  {
    background-color: @mode;
}

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:

.make-variants(@i:1) when (@i =< 3) {
  .variant-@{i} {
    width: @i * 40px;
    height: @i * 20px;
    background-color: orange;
    margin-bottom: 10px;
    }
  .make-variants(@i + 1); // increment function
}

.make-variants();

We have a counter parameter set to 1 (@i:1) and a condition (@i =< 3) 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:

.variant-1 {
  width: 40px;
  height: 20px;
  background-color: orange;
  margin-bottom: 10px;
}
.variant-2 {
  width: 80px;
  height: 40px;
  background-color: orange;
  margin-bottom: 10px;
}
.variant-3 {
  width: 120px;
  height: 60px;
  background-color: orange;
  margin-bottom: 10px;
}

See the Pen Less Guards and Loops Example 4 by SitePoint (@SitePoint) on CodePen.

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.

Frequently Asked Questions about LESS Guards and Loops

What is the purpose of using guards in LESS?

Guards in LESS are used to apply styles conditionally. They are similar to if-else statements in programming languages. Guards are used in mixins to apply different styles based on certain conditions. They help in creating dynamic stylesheets and make your code more efficient and manageable.

How can I use loops in LESS?

Loops in LESS are used to repeat a block of code multiple times. They are created using recursive mixins. A mixin calls itself until a certain condition is met. This is useful when you want to generate a series of similar styles, like creating a grid system or generating classes for different font sizes.

Can I use logical operators in LESS guards?

Yes, you can use logical operators in LESS guards. The operators include: ‘and’, ‘or’, and ‘not’. These operators can be used to combine or negate conditions in your guards, giving you more control over your styles.

Why are my LESS loops not working?

There could be several reasons why your LESS loops are not working. One common reason is that the termination condition is not met, causing an infinite loop. Another reason could be a syntax error in your mixin or guard. Make sure to check your code carefully for any mistakes.

How can I use variables in LESS guards?

Variables in LESS guards are used to make your styles more dynamic. You can define a variable and use it in your guard condition. When the condition is met, the styles in the mixin are applied. This allows you to create styles that can change based on the value of the variable.

Can I use functions in LESS guards?

Yes, you can use functions in LESS guards. Functions can be used to manipulate values or perform calculations in your guard conditions. This can be useful when you want to apply styles based on the result of a function.

How can I create nested loops in LESS?

Nested loops in LESS can be created by placing a loop inside another loop. This is useful when you want to generate a series of styles that depend on multiple variables. However, be careful when creating nested loops as they can quickly become complex and difficult to manage.

Can I use guards in LESS without mixins?

No, guards in LESS are used specifically with mixins. They are used to apply styles conditionally based on the guard condition. Without a mixin, there would be no styles to apply, making the guard useless.

How can I use the ‘when’ keyword in LESS guards?

The ‘when’ keyword in LESS guards is used to specify the condition for the guard. It is followed by a condition that must be met for the styles in the mixin to be applied. The ‘when’ keyword makes your guards more readable and easier to understand.

Can I use loops in LESS to generate a series of classes?

Yes, you can use loops in LESS to generate a series of classes. This is useful when you want to create a set of similar classes with different values. For example, you can create a loop to generate classes for different font sizes or colors.

Ivaylo GerchevIvaylo Gerchev
View Author

I am a web developer/designer from Bulgaria. My favorite web technologies include SVG, HTML, CSS, Tailwind, JavaScript, Node, Vue, and React. When I'm not programming the Web, I love to program my own reality ;)

LESSless guardsless loopsLess Mixins
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week