Skip to content

Control Directives & Expressions

Sass provides control directives that allow you to include styles conditionally or repeatedly based on SassScript expressions. These are powerful tools, often used within mixins and functions, enabling dynamic and complex stylesheet generation.

The @if directive evaluates a SassScript expression. If the expression returns true (or any value other than false or null), the styles within its block are output. You can chain @else if for multiple conditions and end with an optional @else block for the default case.

Syntax:

@if condition1 {
// Styles if condition1 is true
} @else if condition2 {
// Styles if condition1 is false and condition2 is true
} @else {
// Styles if all preceding conditions are false
}

Example: Creating theme styles.

$theme: light;
.widget {
border: 1px solid;
@if $theme == dark {
background-color: #333;
color: #eee;
border-color: #555;
} @else if $theme == sepia {
background-color: #f4ecd8;
color: #5b4636;
border-color: #d8c8a8;
} @else {
// Default light theme
background-color: #fff;
color: #333;
border-color: #ccc;
}
}

Sass also provides a ternary if(condition, value-if-true, value-if-false) function, useful for assigning one of two values to a variable or property based on a condition.

$text-color: if($theme == dark, white, black);
.element {
color: $text-color;
}

The @for directive creates a loop, typically used to generate styles based on a numerical sequence. It uses a counter variable that increments (or decrements) through a specified range.

Syntax:

// 'through' includes the end value
@for $var from <start> through <end> {
// Styles using #{$var}
}
// 'to' excludes the end value
@for $var from <start> to <end> {
// Styles using #{$var}
}

Example: Generating grid column classes.

$grid-columns: 12;
@for $i from 1 through $grid-columns {
.col-#{$i} {
width: (100% / $grid-columns) * $i;
}
}

Compiled CSS (partial):

.col-1 {
width: 8.3333333333%;
}
.col-2 {
width: 16.6666666667%;
}
/* ... up to .col-12 */
.col-12 {
width: 100%;
}

The @each directive iterates over items in a list or pairs in a map. It’s extremely useful for generating variations of styles based on a collection of values.

Syntax (List):

@each $var in <list> {
// Styles using #{$var}
}

Syntax (Map):

@each $key, $value in <map> {
// Styles using #{$key} and #{$value}
}

Example (List): Generating background color utility classes.

$colors: primary, secondary, success, danger, warning, info;
$color-map: (
primary: blue,
secondary: gray,
success: green,
danger: red,
warning: orange,
info: teal
);
@each $name in $colors {
.bg-#{$name} {
background-color: map-get($color-map, $name);
}
}

Example (Map): Generating social media button styles.

$social-colors: (
twitter: #1DA1F2,
facebook: #1877F2,
linkedin: #0A66C2
);
@each $network, $color in $social-colors {
.button--#{$network} {
background-color: $color;
color: white;
&:hover {
background-color: darken($color, 10%);
}
}
}

The @while directive continues to output styles as long as its condition evaluates to true. It’s less commonly used than @for or @each because you typically need to manage the loop variable manually to avoid infinite loops.

Syntax:

@while condition {
// Styles
// Make sure to update variable(s) used in condition!
}

Example: Generating heading styles with decreasing font sizes.

$level: 6;
$font-size: 1rem;
@while $level > 0 {
h#{$level} {
font-size: $font-size;
}
$level: $level - 1;
$font-size: $font-size * 1.2; // Increase size for next level up
}

Control directives are essential for:

  • Creating themes and variations.
  • Generating utility classes.
  • Building complex grid systems.
  • Writing flexible mixins that adapt based on input.
  • Automating repetitive CSS patterns.

Use them thoughtfully to keep your Sass code readable and maintainable. Overuse can sometimes lead to overly complex and hard-to-debug CSS.