SyntaxStudy
Sign Up
SASS / SCSS Beginner 1 min read

@for and @while Loops

The `@for` directive iterates over a range of integers. The syntax `@for $i from 1 through 5` iterates inclusively from 1 to 5. Using `to` instead of `through` makes the end exclusive: `@for $i from 1 to 5` goes from 1 to 4. The loop variable `$i` is available inside the block and is commonly used with string interpolation (`#{}`) to generate numbered class names or calculate values. The `@while` directive repeats its block as long as a condition is true. It is the most flexible loop type but also the most dangerous — a bug in the condition can cause an infinite loop. In practice, `@while` is rarely needed because `@for` and `@each` cover most use cases. One legitimate use case is generating a geometric progression (doubling or halving values) where the stop condition depends on the computed value rather than a fixed count. A common pattern with `@for` is generating spacing utility classes, grid column widths, font-size scales, opacity steps, or z-index layers. Combined with SASS math functions, `@for` can generate entire design system scales from a single configuration value.
Example
// ── @for through (inclusive) ─────────────────────────────────────────────────

@use 'sass:math';

// Spacing utility classes: .mt-1 through .mt-8
@for $i from 1 through 8 {
    .mt-#{$i} { margin-top   : #{$i * 0.25}rem; }
    .mb-#{$i} { margin-bottom: #{$i * 0.25}rem; }
    .pt-#{$i} { padding-top  : #{$i * 0.25}rem; }
    .pb-#{$i} { padding-bottom: #{$i * 0.25}rem; }
}

// Grid column utilities: .col-1 through .col-12
@for $i from 1 through 12 {
    .col-#{$i} {
        width: math.percentage(math.div($i, 12));
    }
}

// Opacity utilities: .opacity-10, .opacity-20 … .opacity-100
@for $i from 1 through 10 {
    .opacity-#{$i * 10} {
        opacity: math.div($i, 10);
    }
}

// ── @for to (exclusive upper bound) ──────────────────────────────────────────

// Generates .heading-1 through .heading-5 (stops before 6)
@for $i from 1 to 6 {
    .heading-#{$i} {
        font-size  : #{(2.5 - ($i - 1) * 0.35)}rem;
        font-weight: if($i <= 2, 800, 700);
        line-height: 1.2;
    }
}

// ── @while for geometric progressions ────────────────────────────────────────

$z-index : 100;
$level   : 1;

@while $z-index <= 1600 {
    .z-#{$level} { z-index: $z-index; }
    $z-index : $z-index * 2;  // doubles each step: 100 → 200 → 400 → 800 → 1600
    $level   : $level + 1;
}