@while
@while loops in Sass: generate repetitive CSS, build grid systems, and stamp out variant classes when @each will not do.
Sass — @while
EXAMPLE
// ===== Basic @while =====
// Generate a set of spacing utility classes:
$i: 0;
@while $i <= 10 {
.mt-#{$i} { margin-top: #{$i * 0.25}rem; }
$i: $i + 1;
}
// Compiles to .mt-0 { margin-top: 0; } ... .mt-10 { margin-top: 2.5rem; }
// ===== When @while wins =====
// - Loop with a condition that is not a simple range
// - Build sequences where the step depends on the value
// - Stop when a property hits a threshold
@use 'sass:math';
@function fibonacci($n) {
$a: 0;
$b: 1;
@while $n > 0 {
$tmp: $a + $b;
$a: $b;
$b: $tmp;
$n: $n - 1;
}
@return $a;
}
.fib-5 { width: #{fibonacci(5)}px; } // 5
// ===== @while for grid systems =====
$cols: 12;
$i: 1;
@while $i <= $cols {
.col-#{$i} { width: math.div($i, $cols) * 100%; }
$i: $i + 1;
}
// .col-1 { width: 8.333%; } ... .col-12 { width: 100%; }
// ===== @while vs @for vs @each =====
// @for $i from 1 through 10 for known ranges (preferred when possible)
// @each $name in (a, b, c) for explicit lists
// @while ... for everything else
// ===== Bail-out conditions =====
// Always increment the loop variable; otherwise infinite loop.
// Sass compilers detect runaway loops and abort, but only after burning cycles.
// ===== Pitfalls =====
// - Forgetting $i: $i + 1 -> infinite loop
// - Heavy @while in production -> long compile times
// - Generating thousands of selectors that purge later wastes both build + parse time
// - Preferring @while when @for / @each would read better
// ===== Patterns to internalise =====
// - @for over @while when the bounds are known
// - @while only for variable-step or condition-based loops
// - Generate purgeable utility classes; pair with a purge step or Tailwind
// - Output the smallest necessary CSS; selectors are not free
// ===== A combined example: typographic scale =====
$base-size: 1rem;
$ratio: 1.25; // Major third
$max-step: 6;
@function scale($step) {
$val: $base-size;
$i: 0;
@while $i < $step {
$val: $val * $ratio;
$i: $i + 1;
}
@return $val;
}
.text-base { font-size: $base-size; }
.text-lg { font-size: scale(1); }
.text-xl { font-size: scale(2); }
.text-2xl { font-size: scale(3); }
.text-3xl { font-size: scale(4); }
Why it matters
@while fills the niche between @for(known ranges) and @each(explicit lists): loops with a condition or variable step. Use it sparingly; prefer @for / @each when they fit. The wins are computed typographic scales, grid systems, and the rare numeric algorithm that needs a stop condition.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Discussion
Loading…