CSS PREprocessors

Loops

by

Loops are useful when you need to create a set of selectors/values that have an underlying mathematical relation of some sort.

Basic loop

Let's build something simple - a very basic grid system with four columns.

We will put the columns class name and their number in variables and utilize them through variable interpolation.

.generate-column(@i: 1) when (@i =< 4) {
  [email protected]{i} {
    width: @i * (100% / 4);
  }
  .generate-column(@i + 1);
}

.generate-column();
.col {
  .-(@i: 1) when (@i =< 4) {
    &[email protected]{i} {
      width: @i * (100% / 4);
    }.-(@i + 1);
  }.-;
}
@for $i from 1 through 4 {
  .col-#{$i} {
    width: $i * (100% / 4);
  }
}
@for $i from 1 through 4
  .col-#{$i}
    width: $i * (100% / 4)
for $i in 1..4
  .col-{$i}
    width: $i * (100% / 4)
@for $i from 1 to 4 {
  .col-$(i) {
    width: resolve($(i) * resolve(100 / 4))%;
  }
}
.col-1 {
  width: 25%;
}
.col-2 {
  width: 50%;
}
.col-3 {
  width: 75%;
}
.col-4 {
  width: 100%;
}

You will notice that Less offers two ways to write a loop, the first way is standard with a mixin that is later called. The second one is a bit hacky and much uglier, but doesn't require calling the mixin later.

In all of the preprocessors you can have both inclusive ranges and exclusive ones. For Less an inclusive range can be achieved with =< and for an exclusive one - <. In Sass inclusive ranges use through and exclusive - to. For Stylus inclusive ranges are written with .. and exclusive - ....

Leveling up

Often when you do a loop you want to iterate through something more than numbers, probably a list of colors or some other values. Here is an example of how you can create numbered selectors with values, extracted from a variable.

@colors: #012345, #6789ab, #abcdef;

.color-mixin(@colors; @n) when (@n > 0) {
  .color-mixin(@colors; (@n - 1));
  @i: @n - 1;
  [email protected]{i} {
    background-color: extract(@colors, @n);
  }
}
.color-mixin(@colors; length(@colors));
$colors: #012345, #6789ab, #abcdef;

@for $i from 1 through length($colors) {
  .color-#{$i - 1} {
    background: #{nth($colors, $i)};
  }
}
$colors: #012345, #6789ab, #abcdef;

@each $color in $colors {
  $i: index($colors, $color);
  .color-#{$i - 1} {
    background: $color;
  }
}
$colors: #012345, #6789ab, #abcdef

@for $i from 1 through length($colors)
  .color-#{$i - 1}
    background: #{nth($colors, $i)}
$colors: #012345, #6789ab, #abcdef

@each $color in $colors
  $i: index($colors, $color)
  .color-#{$i - 1}
    background: $color
$colors = #012345, #6789ab, #abcdef

for $color, $i in $colors
  .color-{$i}
    background: $color
$colors = #012345, #6789ab, #abcdef;
@each $color, $i in ($colors) {
  .color-$(i) {
    background: $(color);
  }
}
.color-0 {
  background: #012345;
}
.color-1 {
  background: #6789ab;
}
.color-2 {
  background: #abcdef;
}

In addition to an index-based iteration, Sass can also iterate through values directly. As Sass does not yet provide an index variable when iterating values, we have to retrieve it manually.

Interactive

Leave a comment below or suggest improvements on GitHub.