Register to get access to free programming courses with interactive exercises

Cycles SASS: Programming

The cornerstone of the SASS preprocessor is loops. They allow repeatedly executing any sequence of actions.

In SASS, loops often generate many classes, which we can use in the project. Before we get down to writing and understanding loops, we will introduce a basic example on which we will study all possible types of loops in the SASS preprocessor.

Let us imagine that we have a list with five elements inside it:

  • cat
  • dog
  • whale
  • bird
  • fish

We need to make a class of the following kind for each element of the list:

.icon-cat {
  height: 32px;
  width: 32px;

  background: url("../icon/svg/cat.svg");
}

What paths can we take now? The first thing that comes to mind is the use of mixins. It is a good option, which fully satisfies our needs:

$icons: "cat", "dog", "whale", "bird", "fish";

@mixin icon-32($icon-name) {
  .icon-#{$icon-name} {
    height: 32px;
    width: 32px;

    background: url("../icon/svg/#{$icon-name}.svg");
  }
}

We need to execute this mixin for each item in the list to generate icons. That is, five times:

@include icon-32(nth($icons, 1));
@include icon-32(nth($icons, 2));
@include icon-32(nth($icons, 3));
@include icon-32(nth($icons, 4));
@include icon-32(nth($icons, 5));

The icons are ready! It is acceptable if we have five icons. But what if we have 20 icons in the project? Or even 100? Maybe you are creating your library of icons. In that case, using the method above is not the best way. It will give you the needed results, but the number of lines you copy is high. So, how can we make life easier? Well, we have loops in SASS for that. We will try one of them right now!

The cycle for

The for loop allows us to set the number of repetitions. It is helpful if we know or calculate the required number of repetitions of a block of code.

Let us try to write such a loop. We use the @for construction, for which you need to write a counter. The counter is a simple mechanism to specify the start and end values. Each time you execute a code block, the loop first increments the counter by one and then checks to see if the value has exceeded the limit. If not, we execute the code block again.

We can write the counter in the @for loop of one of two kinds. Here you see the examples for a counter from 1 to 5:

  • from 1 to 5. The counter with the to keyword counts to a finite number, not including border numbers. In this variant, a loop will execute the code block 4 times
  • from 1 through 5. A counter with the through keyword counts up to a finite number, including border numbers. A loop with this counter will execute the code block 5 times

We write all counter values to a variable whose name you specify immediately after the @for keyword. The complete loop entry is as follows:

@for $i from 1 to 5 {
  // The program will execute the code block four times
}

We can use a declared variable as a counter inside a loop. It is easy to see this in the following example:

@for $i from 1 to 5 {
  $side: $i * 10;

  .square-#{$side} {
    display: block;

    width: #{$side}px;
    height: #{$side}px
  }
}

We use the $i counter to calculate the required side of the square. The result of the compilation is the following CSS code:

.square-10 {
  display: block;
  width: 10px;
  height: 10px;
}

.square-20 {
  display: block;
  width: 20px;
  height: 20px;
}

.square-30 {
  display: block;
  width: 30px;
  height: 30px;
}

.square-40 {
  display: block;
  width: 40px;
  height: 40px;
}

We used to in the counter condition and generated four classes.

Now the solution to the original problem becomes a bit easier. We can use the @for loop and generate classes as many times as we need:

$icons: "cat", "dog", "whale", "bird", "fish";

@mixin icon-32($icon-name) {
  .icon-#{$icon-name} {
    height: 32px;
    width: 32px;

    background: url("../icon/svg/#{$icon-name}.svg");
  }
}

@for $i from 1 through 5 {
  @include icon-32(nth($icons, $i));
}

You may have noticed a problem with this code — you need to know the number of items in the list. And as long as this number is small, everything is fine again. But as soon as these items become 78, for example, it is not very pleasant to recalculate them manually every time to change the counter.

Maybe there is a way to give counting to SASS? Of course, there is. You can use the length() function and get the number of elements in the list. In that case, our code could look like this:

$icons: "cat", "dog", "whale", "bird", "fish";
$icons-length: length($icons);

@mixin icon-32($icon-name) {
  .icon-#{$icon-name} {
    height: 32px;
    width: 32px;

    background: url("../icon/svg/#{$icon-name}.svg");
  }
}

@for $i from 1 through $icons-length {
  @include icon-32(nth($icons, $i));
}

Cycle of each

The second way to solve the problem of generating classes with icons is the @each loop. This loop searches through the values of a list or an associative array and execute a code block for each value. With this loop, we do not have to know the list size or create counters. We work directly with each value.

The @each loop is ideal for generating classes based on a list or an associative array. To use it, you have to use the keyword @each. After that, you specify the variable in which we will store the current value from the list.

After that, we specify the list from which we take these values:

$list: 1, 2, 3;

@each $number in $list {
  // code block
}

We can read this loop as follows: For each number in the list, execute and then a code block. It is a way to bypass the list without creating separate variables or referring to the list with nth() as we did in the @for loop variant.

Let us move our icon generation task by replacing the @for loop with the @each loop:

$icons: "cat", "dog", "whale", "bird", "fish";

@mixin icon-32($icon-name) {
  .icon-#{$icon-name} {
    height: 32px;
    width: 32px;

    background: url("../icon/svg/#{$icon-name}.svg");
  }
}

@each $icon in $icons {
  @include icon-32($icon);
}

Now this is good. We used the loop we needed, reducing the number of lines and increasing readability.


Tip: Always pay attention to the operation you are doing. If you need to execute a block of code a certain number of times, use the @for loop. When working with lists/arrays and using their values, use the @each loop. In most cases, this separation will help make your code cleaner


In the example above, we saw how to bypass lists with @each. But with associative arrays, things are a bit different. As you may remember, unlike lists, which enumerate values, associative arrays have key-value pairs. The @each loop gets a key and a value inside a code block. To do this, you specify a comma-separated variable for the key and a value variable. Otherwise, the principle is the same.

As an example, we take the more complex structure of our list of icons, and in addition to the name as a key, they will also contain the size of the icons in the form of a list we have in our project. In this variant, we will combine an associative array and a list:

$icons: (
  "cat": (32, 64, 128),
  "dog": (32, 64, 128),
  "whale": (32, 64),
  "bird": (16, 32, 64, 128),
  "fish": (32, 64)
);

@mixin icon($icon-name, $icon-size) {
  .icon-#{$icon-size}-#{$icon-name} {
    height: #{$icon-size}px;
    width: #{$icon-size}px;

    background: url("../icon/svg/#{$icon-size}/#{$icon-name}.svg");
  }
}

@each $icon, $sizes in $icons {
  @each $size in $sizes {
    @include icon($icon, $size);
  }
}

After compiling, we get the following CSS code for the cat icons:

.icon-32-cat {
  height: 32px;
  width: 32px;
  background: url("../icon/svg/32/cat.svg");
}

.icon-64-cat {
  height: 64px;
  width: 64px;
  background: url("../icon/svg/64/cat.svg");
}

.icon-128-cat {
  height: 128px;
  width: 128px;
  background: url("../icon/svg/128/cat.svg");
}

The program will generate the rest of the classes similarly.

In this example, you can see that we can nest loops inside each other. These loops can be of different types. We can put @each inside @for and vice versa. In each of these cases, everything will work correctly. The important thing is that the variables from the outer loop also go into the inner one.

That is why we could use the variable $icon inside the second @each loop created before it.

Cycle while

The last kind of loop in SASS is the @while loop. From its name, we can conclude that it works according to the principle while we fulfill a condition.

For the @while loop, you must specify a condition. As long as we meet it, the program executes the loop.

We use the same constructions as with the conditional @if/@else constructions as a condition:

$count: 1;

@while $count < 5 {
  .font-size-#{$count} {
    font-size: #{$count}em;
  }

  $count: $count + 1;
}

After compiling, you will get the following CSS code:

.font-size-1 {
  font-size: 1em;
}

.font-size-2 {
  font-size: 2em;
}

.font-size-3 {
  font-size: 3em;
}

.font-size-4 {
  font-size: 4em;
}

The @while loop can be complicated because it is easy to forget to work with a condition and go into an infinite loop.

The loop will never end if we forget to specify $count: $count + 1;. Always check that the condition changes after the program executes each code block.


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

Bookmate
Health Samurai
Dualboot
ABBYY
Suggested learning programs
profession
Layout with the latest CSS standards
5 months
from scratch
under development
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.