Sass @else if Rule

Beginner
⏱️ 12 min read
📚 Updated: Jul 2026
🎯 5 Examples
Multi-branch

What You’ll Learn

Sass @else if extends an @if chain with more tested branches. This page focuses on multi-condition chains: first match wins, optional final @else, keyword APIs, and five compiled examples.

01

Chain

@else if

02

Order

First match

03

Fallback

Final @else

04

Keywords

up / right / …

05

APIs

Mixins & funcs

06

Practice

5 examples

What Is @else if?

Official docs: you can choose whether to evaluate an @else rule’s block by writing it @else if <expression> { … }. The block is evaluated only if the preceding @if’s expression returns false (falsey) and the @else if’s expression returns true (truthy).

You can chain as many @else ifs as you want after an @if. The first block in the chain whose expression is truthy will be evaluated, and no others. If there is a plain @else at the end, its block runs when every other test fails.

  • Always part of an @if chain—not a standalone rule.
  • Evaluated in source order; first truthy branch wins.
  • Later @else if / @else blocks are skipped after a match.
  • Compile-time only—never appears in the CSS file.
💡
Beginner tip

Use @if alone for optional styles, @else for two outcomes, and @else if when you have three or more named cases.

📝 Syntax

styles.scss
@if $direction == up {
  border-bottom-color: $color;
} @else if $direction == right {
  border-left-color: $color;
} @else if $direction == down {
  border-top-color: $color;
} @else if $direction == left {
  border-right-color: $color;
} @else {
  @error "Unknown direction #{$direction}.";
}

Each } @else if … { continues the same chain. Keep comparisons mutually exclusive when possible so order does not surprise you.

🎯 First Match Wins

Sass walks the chain from top to bottom:

  1. Test the opening @if.
  2. If falsey, test each @else if in order.
  3. Stop at the first truthy block and run only that block.
  4. If none match and a final @else exists, run that fallback.
⚠️
Order matters

Put more specific conditions before broader ones. A wide test early in the chain can shadow later branches that never get a chance to run.

🛡️ The Final @else

A trailing @else is optional but powerful:

  • Hard fail@error "Unknown …" for invalid API values.
  • Soft default — emit a safe “info” tone or base size.

For public mixins and functions, preferring @error in the final @else catches typos early in CI.

⚖️ @if vs @else vs @else if

NeedUse
Optional extra styles@if only
Exactly two exclusive outcomes@if / @else
Three or more named cases@if / @else if / … / @else

⚡ Quick Reference

GoalCode
Add another test} @else if $x == a { … }
Chain many cases@if … @else if … @else if …
Final fallback} @else { … }
Reject unknowns} @else { @error "…"; }
Two outcomes onlyPrefer @else
Optional block onlyPrefer @if

Examples Gallery

Each example uses an @if / @else if chain (often with a final @else). Open View Compiled CSS for verified output.

📚 Getting Started

Keyword branches with a hard-fail fallback.

Example 1 — Directional Triangle

Official-style mixin: one CSS triangle, four directions, @error otherwise.

styles.scss
@use "sass:math";

@mixin triangle($size, $color, $direction) {
  height: 0;
  width: 0;

  border-color: transparent;
  border-style: solid;
  border-width: math.div($size, 2);

  @if $direction == up {
    border-bottom-color: $color;
  } @else if $direction == right {
    border-left-color: $color;
  } @else if $direction == down {
    border-top-color: $color;
  } @else if $direction == left {
    border-right-color: $color;
  } @else {
    @error "Unknown direction #{$direction}.";
  }
}

.next {
  @include triangle(5px, black, right);
}

.up {
  @include triangle(8px, #036, up);
}

How It Works

Shared triangle setup sits above the chain. Only the matching direction branch adds a colored border. An invalid $direction hits @error.

Example 2 — Heading Levels

Map a numeric level to type styles; soft default for anything else.

styles.scss
@mixin heading($level: 1) {
  margin: 0 0 0.5rem;
  font-weight: 700;

  @if $level == 1 {
    font-size: 2rem;
    line-height: 1.2;
  } @else if $level == 2 {
    font-size: 1.5rem;
    line-height: 1.25;
  } @else if $level == 3 {
    font-size: 1.25rem;
    line-height: 1.3;
  } @else {
    font-size: 1rem;
    font-weight: 600;
  }
}

.h1 { @include heading(1); }
.h2 { @include heading(2); }
.h3 { @include heading(3); }
.h4 { @include heading(4); }

How It Works

Levels 1–3 hit dedicated branches. Level 4 falls through to the final @else default.

📈 Alerts, Tokens & Breakpoints

Named API values mapped through an ordered chain.

Example 3 — Alert Tones

success / warning / danger, with info as the soft @else.

styles.scss
@mixin alert($tone: info) {
  padding: 0.75rem 1rem;
  border-radius: 4px;
  border: 1px solid transparent;

  @if $tone == success {
    background: #e8f6ee;
    border-color: #2f9e64;
    color: #1b5e3b;
  } @else if $tone == warning {
    background: #fff6e5;
    border-color: #e6a700;
    color: #7a5b00;
  } @else if $tone == danger {
    background: #fdecee;
    border-color: #d64550;
    color: #8a1f28;
  } @else {
    background: #eef3ff;
    border-color: #3b6de0;
    color: #1f3f8f;
  }
}

.ok { @include alert(success); }
.warn { @include alert(warning); }
.bad { @include alert(danger); }
.info { @include alert(); }

How It Works

Each tone is an exclusive branch. The default info parameter lands in @else without needing its own @else if.

Example 4 — Spacer Scale Function

Return spacing tokens from a function chain; error on unknown sizes.

styles.scss
@function spacer($size) {
  @if $size == xs {
    @return 0.25rem;
  } @else if $size == sm {
    @return 0.5rem;
  } @else if $size == md {
    @return 1rem;
  } @else if $size == lg {
    @return 1.5rem;
  } @else if $size == xl {
    @return 2rem;
  } @else {
    @error "Unknown spacer size `#{$size}`.";
  }
}

.stack {
  padding: spacer(md);
  gap: spacer(sm);
}

.hero {
  margin-bottom: spacer(xl);
}

How It Works

Each call resolves to one @return. Unknown names never silently become 0—they hit @error.

Example 5 — Breakpoint Name → Padding

Reuse one mixin from several media queries with different keywords.

styles.scss
@mixin breakpoint-padding($name) {
  @if $name == mobile {
    padding: 1rem;
  } @else if $name == tablet {
    padding: 1.5rem;
  } @else if $name == desktop {
    padding: 2rem;
  } @else {
    padding: 1rem;
  }
}

.shell {
  @include breakpoint-padding(mobile);
}

@media (min-width: 768px) {
  .shell {
    @include breakpoint-padding(tablet);
  }
}

@media (min-width: 1024px) {
  .shell {
    @include breakpoint-padding(desktop);
  }
}

How It Works

The mixin stays a pure keyword map. CSS media queries decide when each branch is included; @else if decides which padding value.

🚀 Real-World Use Cases

  • Directional / positional APIs — up, right, down, left.
  • Design tokens — size scales, alert tones, z-index layers.
  • Typography maps — heading levels and display sizes.
  • Function lookups — named spacers with @return.
  • Breakpoint helpers — named layouts inside media queries.

🧠 How Compilation Works

1

Start at @if

Evaluate the first condition in the chain.

Test
2

Walk @else if

Try each additional condition until one is truthy.

Chain
3

Run one block

Emit that branch (or the final @else / @error).

Win
4

CSS ships

Only the winning branch’s styles appear in the output.

⚠️ Common Pitfalls

  • Overlapping conditions — an early broad test can hide later branches.
  • Missing final @else — unknown values may emit nothing silently.
  • Using @else if for two cases — a simple @else is clearer.
  • Forgetting shared styles — put common declarations above the chain.
  • Typos in keywords — prefer @error in the final @else for public APIs.

💡 Best Practices

✅ Do

  • Keep cases mutually exclusive when you can
  • Order specific tests before broader ones
  • Document allowed keywords in the mixin/function name or comment
  • Use @error for invalid public API values
  • Share setup styles outside the chain

❌ Don’t

  • Duplicate huge blocks in every branch
  • Rely on silent no-ops for typos
  • Build giant chains when a map lookup would be clearer
  • Mix unrelated decisions in one chain
  • Expect the chain to re-run in the browser

Key Takeaways

Knowledge Unlocked

Five things to remember about Sass @else if

Ordered multi-branch tests—first truthy block wins.

5
Core concepts
🎯 02

First win

then stop

Order
🛡️ 03

@else

final fallback

Safety
🔢 04

Keywords

named cases

API
05

Compile

one branch CSS

Output

❓ Frequently Asked Questions

It adds another tested branch after an @if. The block runs only if every preceding condition was falsey and this @else if expression is truthy.
As many as you need. Sass evaluates them in order and runs only the first truthy block in the chain.
No. Once one block in the @if / @else if / @else chain succeeds, the rest are skipped.
@else if has its own condition. A plain @else has no condition—it is the final fallback when every prior test failed. See the Sass @else Rule page for two-way branches.
Often yes for public APIs—unknown keywords should fail loudly. Soft defaults in @else are fine when a safe fallback exists.
No. Like @if and @else, it is compile-time only. Browsers see styles from the winning branch only.
Did you know?

Official Sass docs demonstrate @else if with a CSS triangle mixin—one of the clearest ways to see how a single shared setup plus directional branches becomes clean CSS.

Conclusion

@else if turns a simple conditional into an ordered multi-branch decision: test cases in sequence, run the first match, and optionally finish with @else (or @error). Use it for keyword APIs with three or more outcomes.

Continue with @each or @else.

Next: Sass @each

Loop lists and maps to generate repetitive utilities and media queries.

@each rule →

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