Power of Sass: loops

03.05.2024 | Author: Przemysław Kosiński

Sass (Syntactically Awesome Style Sheets) is a powerful CSS preprocessor that makes it easier to create amazing styles for modern website projects. It helps you build clean, maintainable, modular and scalable projects.

Among the many features Sass offers, loops stand out as particularly valuable. Loops let developers write cleaner, more understandable code by automating the generation of repetitive pieces of code. In this article we take a detailed look at loops and show how they can streamline working with CSS on your website.

Understanding loops in Sass

Loops in Sass/SCSS work mostly as they do in other programming languages, letting you iterate over a set of values or elements. They come in two main flavours: @for loops and @each loops.

The @for loop

The @for loop is useful when we need to generate code for a range of numeric values. Its structure and syntax are similar to those commonly known from many other programming languages, and it works almost identically:

@for $variable from <range_start> through <range_end> {
  // loop body
}

In the code above, $variable is the loop variable, which iterates from "range_start" up to and including "range_end" (<=), thanks to the through keyword.

@for $i from 1 through 3 {
  .item-#{$i} {
    width: 100px * $i;
  }
}

This loop will generate CSS rules for three elements:

.item-1 {
  width: 100px;
}

.item-2 {
  width: 200px;
}

.item-3 {
  width: 300px;
}

We can also iterate up to, but not including, the end of the range (<) using the construct below, with the to keyword.

@for $variable from <range_start> to <range_end> {
  // loop body
}

The @each loop

The @each loop, in turn, iterates over lists or maps. Its syntax also follows other common programming languages and looks like this:

@each $variable in <list> {
  // loop body
}

// Example:

$colors: red, green, blue;

@each $color in $colors {
  .btn-#{$color} {
    background-color: $color;
  }
}

This loop will generate CSS rules for .btn-[color] elements with different background colours, as below:

.btn-red {
  background-color: red;
}

.btn-green {
  background-color: green;
}

.btn-blue {
  background-color: blue;
}

Advanced techniques

Nested loops

Another example is a more advanced construct that nests several loops inside one. It uses several types of loops, additional conditions and an object with the necessary data.

The code below lets us generate classes for components that form a complete multi-dimensional grid, including all the necessary media queries (stored in the object). It is a multi-dimensional grid because it does not generate just one column division, like the 12 or 10 columns in popular libraries, but a division into n columns for the given range.

$grid-breakpoints: (xs: 0,  sm: 480,  md: 768,  lg: 1024,  xl: 1200,  max: 1600);

@each $grid_name, $grid_val in $grid-breakpoints {  
  @media only screen and (min-width: $grid_val + 'px') {
    @for $x from 1 through 5 {
        @for $y from 1 to $x + 1 {
            @if $grid_name != xs {
              .col-#{$grid_name}-#{$x}-#{$y} {
                  flex-basis: percentage(calc($y / $x));
              }
            } @else {
              .col-#{$x}-#{$y} {
                  flex-basis: percentage(calc($y / $x));
              }
            }
        }
    }
  }
}

Thanks to the example above, practically 3 lines of code (not counting another 3 lines for the first condition, for base-mobile classes without a resolution level) turn into a full n-dimensional grid, generating around 280 lines of code. Depending on the threshold condition of the second main loop, we get a division into n columns with full coverage. This is easier to explain with fragments generated by the loop above.

Increasing the range to, for example, 12, as in the popular Bootstrap, generates more than 1,400 lines of code. Of course, the whole thing can be compressed further and additional conditions added to avoid repetition, but compared with trying to cover such a grid by hand, the savings in time, modularity and maintenance are on a completely different level.

.col-1-1 {
    flex-basis: 100%;
  }
  .col-2-1 {
    flex-basis: 50%;
  }
  .col-2-2 {
    flex-basis: 100%;
  }
  .col-3-1 {
    flex-basis: 33.3333333333%;
  }
  .col-3-2 {
    flex-basis: 66.6666666667%;
  }
  .col-3-3 {
    flex-basis: 100%;
  }
  .col-4-1 {
    flex-basis: 25%;
  }
  .col-4-2 {
    flex-basis: 50%;
  }
  .col-4-3 {
    flex-basis: 75%;
  }
  .col-4-4 {
    flex-basis: 100%;
  }
  .col-5-1 {
    flex-basis: 20%;
  }
  .col-5-2 {
    flex-basis: 40%;
  }
  .col-5-3 {
    flex-basis: 60%;
  }
  .col-5-4 {
    flex-basis: 80%;
  }
  .col-5-5 {
    flex-basis: 100%;
  }

// …

@media only screen and (min-width: 1600px) {
  .col-max-1-1 {
    flex-basis: 100%;
  }
  .col-max-2-1 {
    flex-basis: 50%;
  }
  .col-max-2-2 {
    flex-basis: 100%;
  }
  .col-max-3-1 {
    flex-basis: 33.3333333333%;
  }
  .col-max-3-2 {
    flex-basis: 66.6666666667%;
  }
  .col-max-3-3 {
    flex-basis: 100%;
  }

//…

  .col-max-5-1 {
    flex-basis: 20%;
  }
  .col-max-5-2 {
    flex-basis: 40%;
  }
  .col-max-5-3 {
    flex-basis: 60%;
  }
  .col-max-5-4 {
    flex-basis: 80%;
  }
  .col-max-5-5 {
    flex-basis: 100%;
  }
}

Dynamic property names

We can use Sass interpolation to generate dynamic property names:

$attributes: top, bottom, right, left;

@each $attr in $attributes {
  .element {
    #{$attr}: 100px;
  }
}

// What the code above will generate

.element {
  top: 100px;
}
.element {
  bottom: 100px;
}
.element {
  right: 100px;
}
.element {
  left: 100px;
}

We can also easily modify the loop to combine all the generated attributes into a single declaration, as in the example below.

.element {
  @each $attr in $attributes {
    #{$attr}: 100px;
  }
}

// the result is the code below

.element {
  top: 100px;
  bottom: 100px;
  right: 100px;
  left: 100px;
}

Benefits of loops in Sass/SCSS

To sum up the examples above and this brief presentation of what loops in Sass can do, let’s look at the most important benefits of using them in our projects.

The DRY principle

Loops follow the DRY (Don’t Repeat Yourself) principle by eliminating redundant code. Instead of writing similar CSS rules by hand, you can use loops to generate them dynamically.

Maintenance

By reducing repetitive code, loops make style sheets easier to maintain. When you need to make changes, you just update the loop logic instead of searching for and modifying code repeated many times.

Scalability

As a project grows, loops make scaling easier. Adding new elements or properties becomes simple, because you can rely on loops to handle repetitive tasks automatically.

Summary

Loops in Sass/SCSS are essential tools for processing CSS, enabling developers to write cleaner and more efficient code. By automating repetitive tasks, loops follow the DRY principle, make code easier to keep up to date and simplify scaling. Whether you iterate over numeric values or lists, loops streamline working with CSS and help you build solid, maintainable style sheets. Mastering loops in Sass/SCSS is a basic step towards building consistent, modern layouts in modern website projects.

Related technologies

Przemysław Kosiński Przemysław Kosiński

frontend developer

I am an experienced frontend developer. I remember the days of Internet Explorer 6, so nothing scares me ;). I am a fan of the new solutions in HTML5 and CSS3, which more and more natively make it possible to build modern, attractive features.

All articles by this author

Share

Rate this article

Let’s talk
about your project

+48 506 160 480
biuro@okinet.pl

or write to us