Loops: @each and @for
A loop repeats a block of code for every item of a list or for every number in a range. In Sass loops are used to generate CSS: one short loop turns into dozens of similar classes — colours, gaps, column widths. The browser gets the finished classes.
Interpolation
To make a class name from a value, insert it into the selector with #{}. This is interpolation:
// styles/main.scss
$name: "primary";
.text-#{$name} {
color: #2563eb;
}.text-primary {
color: #2563eb;
}Without the brackets, .text-$name is a syntax error: in a selector Sass does not look for variables.
@each over a list
@each takes the items of a list one by one into a variable. Utility classes get their own folder; create styles/utilities/_text-align.scss:
// styles/utilities/_text-align.scss
@each $align in left, center, right {
.text-#{$align} {
text-align: $align;
}
}// styles/main.scss
@use "utilities/text-align";.text-left {
text-align: left;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}Three rules from four lines. Adding justify to the list adds the fourth class.
@each over a map
With a map the loop takes two variables — the key and the value. Here the theme colours become text and background classes:
// styles/utilities/_colors.scss
$colors: (
"primary": #2563eb,
"success": #16a34a,
"danger": #dc2626,
);
@each $name, $color in $colors {
.bg-#{$name} {
color: white;
background: $color;
}
}// styles/main.scss
@use "utilities/colors";.bg-primary {
color: white;
background: #2563eb;
}
.bg-success {
color: white;
background: #16a34a;
}
.bg-danger {
color: white;
background: #dc2626;
}<style>
.bg-primary {
color: white;
background: #2563eb;
}
.bg-success {
color: white;
background: #16a34a;
}
.bg-danger {
color: white;
background: #dc2626;
}
</style>
<p class="bg-primary">Information</p>
<p class="bg-success">Saved</p>
<p class="bg-danger">Error</p>@for — counting
@for repeats a block for numbers in a range. from 1 through 4 includes 4; from 1 to 4 stops before it. Here is a margin scale with a step of 8px:
// styles/utilities/_spacing.scss
@for $i from 1 through 4 {
.mt-#{$i} {
margin-top: $i * 8px;
}
}// styles/main.scss
@use "utilities/spacing";.mt-1 {
margin-top: 8px;
}
.mt-2 {
margin-top: 16px;
}
.mt-3 {
margin-top: 24px;
}
.mt-4 {
margin-top: 32px;
}Which loop to choose
| Task | Loop |
|---|---|
| Classes from a list of words | @each $item in ... |
| Classes from named values | @each $key, $value in $map |
Numbered classes: .mt-1, .col-6 | @for $i from 1 through N |
There is also @while, which repeats while a condition is true, but @each and @for cover almost every case and cannot loop forever.
Common mistake
Loops make it easy to generate far more CSS than the site uses. Ten colours times six properties times five breakpoints is three hundred classes, most of them never used, and the CSS file becomes heavy. Generate only what the design needs, and check the size of the compiled file after adding a loop.