Sass @while Rule

Intermediate
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
Condition loops

What You’ll Learn

Sass @while repeats a block as long as a condition stays true. This page covers how the loop works, when to prefer @for / @each, safe variable updates, truthiness, and five compiled examples.

01

Loop

@while

02

Condition

Until false

03

Mutate

Update vars

04

Prefer

@for / @each

05

Functions

Scale & strip

06

Practice

5 examples

What Is @while?

Official docs: the @while rule evaluates its block if the expression returns true. Then, if the expression still returns true, it evaluates the block again. This continues until the expression finally returns false.

Write it as @while <condition> { … }. Inside the block you almost always update one or more variables that the condition depends on—otherwise the loop never ends.

  • Compile-time only—browsers never see @while.
  • Best for open-ended or complex stop conditions (not simple 1…n counts).
  • Common inside @function helpers that shrink or grow a value.
  • Only false and null are falsey in Sass.
💡
Beginner tip

Think of @while as “keep doing this until the test fails.” If you already know the count or the list of items, reach for @for or @each first.

⚠️ Prefer @for or @each When You Can

Official docs warn: although @while is necessary for a few particularly complex stylesheets, you are usually better off using either @each or @for if either will work. They are clearer for readers and often faster to compile.

NeedPrefer
Count 1…n@for
Walk a list or map@each
Stop when a value crosses a threshold@while
Complex / unknown iteration count@while

📝 Syntax

styles.scss
$i: 1;

@while $i <= 3 {
  .step-#{$i} {
    order: $i;
  }
  $i: $i + 1; // required — otherwise the loop never stops
}

✅ Truthiness and Falsiness

Official docs: anywhere true or false are allowed, you can use other values. Only false and null are falsey. Every other value is truthy—including 0, empty strings, and empty lists.

💡
Fun fact

Checking for a substring with string.index($str, " ") works as a condition because a missing match returns null (falsey) and a found match returns a number (truthy).

⚡ Quick Reference

GoalCode
Basic loop@while $i <= 4 { …; $i: $i + 1; }
Shrink until below base@while $value > $base { $value: math.div(…); }
Build a list@while $n <= $limit { $out: append(…); }
Stop on null@while string.index($s, "0") == 1 { … }
Prefer simpler loops@for / @each when the range or items are known

Examples Gallery

Each example updates loop state so the condition can become false. Open View Compiled CSS for verified output.

📚 Getting Started

Official-style helpers and a simple counter pattern.

Example 1 — scale-below() (Official Pattern)

Divide a value by the golden ratio until it drops below a base size.

styles.scss
@use "sass:math";

/// Divides `$value` by `$ratio` until it's below `$base`.
@function scale-below($value, $base, $ratio: 1.618) {
  @while $value > $base {
    $value: math.div($value, $ratio);
  }
  @return $value;
}

$normal-font-size: 16px;

sup {
  font-size: scale-below(20px, 16px);
}

How It Works

Start at 20px. While it is greater than 16px, divide by 1.618. When the value finally drops below the base, return it for font-size.

Example 2 — Manual Counter (Like @for)

Increment $i yourself—useful for learning, but prefer @for for this case.

styles.scss
$i: 1;

@while $i <= 4 {
  .step-#{$i} {
    order: $i;
  }
  $i: $i + 1;
}

How It Works

Without $i: $i + 1, the condition stays true forever. For a fixed range, @for $i from 1 through 4 is clearer.

📈 Scales, Halving & Strings

Build lists, shrink sizes, and strip characters until a stop.

Example 3 — Build a Powers-of-Two List

Keep doubling until you pass a limit, then emit gap utilities with @each.

styles.scss
@use "sass:list";

@function powers-of-two($start, $limit) {
  $n: $start;
  $out: ();

  @while $n <= $limit {
    $out: list.append($out, $n);
    $n: $n * 2;
  }

  @return $out;
}

$sizes: powers-of-two(4px, 32px);

@each $size in $sizes {
  .gap-#{$size} {
    gap: $size;
  }
}

How It Works

@while builds the scale; @each turns it into CSS. You do not need to know how many steps fit under $limit ahead of time.

Example 4 — Halve Box Sizes Until a Floor

Emit nested-looking size classes while the current size stays above a base.

styles.scss
@use "sass:math";

$size: 64px;
$base: 8px;
$i: 0;

@while $size > $base {
  .box-#{$i} {
    width: $size;
    height: $size;
  }
  $size: math.div($size, 2);
  $i: $i + 1;
}

How It Works

After emitting 16px, the next half is 8px. Because the test is $size > $base, 8px is not included—another classic inclusive vs exclusive choice.

Example 5 — Strip Leading Zeros From a String

Use string.index as a condition: keep slicing while the first character is 0.

styles.scss
@use "sass:string";
@use "sass:meta";

@function strip-leading-zeros($str) {
  @while string.index($str, "0") == 1 and string.length($str) > 1 {
    $str: string.slice($str, 2);
  }
  @return $str;
}

.result {
  --a: #{meta.inspect(strip-leading-zeros("00042"))};
  --b: #{meta.inspect(strip-leading-zeros("0"))};
  --c: #{meta.inspect(strip-leading-zeros("1050"))};
}

How It Works

string.index($str, "0") == 1 means the string starts with zero. string.length($str) > 1 keeps a lone "0" intact.

🚀 Real-World Use Cases

  • Scale helpers — shrink font or spacing until under a base.
  • Generated sequences — powers of two, Fibonacci-style steps.
  • String cleanup — strip prefixes while a pattern still matches.
  • Complex stop rules — more than one condition must change.
  • Function internals — keep looping logic out of selectors.

🧠 How Compilation Works

1

Test the condition

If the expression is falsey, skip the block and continue compiling.

Check
2

Run the block

Emit CSS and/or update variables used by the condition.

Body
3

Check again

Repeat until the condition becomes false.

Repeat
4

CSS ships

Generated rules or returned values remain; @while does not.

⚠️ Common Pitfalls

  • Infinite loops — forgetting to update the condition’s variables hangs the compiler.
  • Using @while for fixed ranges — prefer @for.
  • Treating 0 as falsey — in Sass, 0 is truthy; only false and null fail.
  • Huge CSS output — a loose condition can emit thousands of rules.
  • Mutating shared state unexpectedly — keep loop variables local inside functions when possible.

💡 Best Practices

✅ Do

  • Reach for @for / @each first when they fit
  • Update every variable the condition depends on
  • Keep complex loops inside @function helpers
  • Use clear stop conditions (> $base, length guards)
  • Test edge cases (exact base, single character, empty input)

❌ Don’t

  • Write @while true without a guaranteed exit
  • Copy-paste counters when @for would read better
  • Assume empty lists or 0 stop the loop
  • Emit unbounded utility classes into production CSS
  • Hide loop logic deep in selectors when a function is clearer

Key Takeaways

Knowledge Unlocked

Five things to remember about Sass @while

Repeat while a condition is true—and always give the loop a way to stop.

5
Core concepts
🔄 02

Mutate

update vars

Safety
⚖️ 03

Prefer

@for / @each

Clarity
04

Falsey

false & null

Truth
05

Functions

great home

Pattern

❓ Frequently Asked Questions

It evaluates a block while its condition expression returns true, then checks again, until the condition finally returns false.
Use @while for open-ended or complex stopping conditions. Prefer @for for numeric ranges and @each for lists or maps—they are clearer and often faster.
Only false and null are falsey. Empty strings, empty lists, and the number 0 are all truthy.
Yes, if the condition never becomes false. Always update the variables that the condition depends on, or the compiler may hang.
No. @while is compile-time only. Browsers see styles or values produced by the loop.
Yes. The official docs show scale-below(), which divides a value until it drops below a base—perfect inside @function.
Did you know?

Official Sass docs recommend @for and @each over @while whenever they fit—not because @while is deprecated, but because fixed ranges and collections are easier to read and often compile faster.

Conclusion

@while is the flexible control rule for open-ended stop conditions: keep running while a test is true, update your variables, and exit cleanly. Reach for it when @for and @each cannot express the logic.

Continue with Sass Numbers or the Sass introduction.

Next: Sass Numbers

Learn values, units, percentages vs decimals, and precision.

Sass Numbers →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful