Skip to content
AgileLogics
7 min read

Sass and Preprocessors

Prerequisites: CSS nesting, Custom properties

Sass is a language that compiles to CSS. It popularized variables, nesting, mixins, and modules long before CSS had any of them. It's still widely used (Bootstrap is written in it), though native CSS now covers much of what it offered. The examples below were compiled with Dart Sass 1.105, the reference implementation.

Sass has two syntaxes; SCSS (.scss), a superset of CSS, is the one everyone uses.

Variables and nesting

$brand: #0b57d0;
$radius: 8px;

.button {
  background: $brand;
  border-radius: $radius;

  &:hover {
    background: #083b8a;
  }

  &--large {
    padding: 1rem 2rem;
  }

  .icon + & {
    margin-left: 0.25rem;
  }
}
.button {
  background: #0b57d0;
  border-radius: 8px;
}
.button:hover {
  background: #083b8a;
}
.button--large {
  padding: 1rem 2rem;
}
.icon + .button {
  margin-left: 0.25rem;
}
  • $variables are replaced at compile time — unlike custom properties, they can't change at run time or per element. Many projects use Sass variables to generate custom properties.
  • Sass nesting can concatenate: &--large became .button--large — handy for BEM, and impossible in native nesting.

Modules, mixins, and functions

@use "sass:math";
@use "sass:color";

$base: 16px;

@function rem($px) {
  @return math.div($px, $base) * 1rem;
}

@mixin focus-ring($color: #f5a623) {
  outline: 3px solid $color;
  outline-offset: 2px;
}

.input {
  padding: rem(12px) rem(16px);
  &:focus-visible {
    @include focus-ring;
  }
}

.danger {
  background: color.change(#c62828, $alpha: 0.1);
}
.input {
  padding: 0.75rem 1rem;
}
.input:focus-visible {
  outline: 3px solid #f5a623;
  outline-offset: 2px;
}

.danger {
  background: rgba(198, 40, 40, 0.1);
}
  • @use loads Sass modules (built-ins like sass:math, or your own files, which are namespaced by file name). The older @import rule is deprecated in Sass and will be removed.
  • @function returns a value; @mixin + @include inserts declarations.
  • In Sass, / is not division — use math.div.

Loops and maps

$sizes: (sm: 0.875rem, md: 1rem, lg: 1.25rem);

@each $name, $size in $sizes {
  .text-#{$name} {
    font-size: $size;
  }
}
.text-sm {
  font-size: 0.875rem;
}

.text-md {
  font-size: 1rem;
}

.text-lg {
  font-size: 1.25rem;
}

#{...} is interpolation — inserting a value into a selector or property name.

Do you still need Sass?

Native CSS now has custom properties, nesting, color-mix(), relative colors, math functions, and layers. What Sass still adds: loops and maps for generating classes, mixins, compile-time functions, and concatenating selectors. Many new projects use plain CSS (maybe with PostCSS or Lightning CSS for compatibility), or a utility framework; Sass remains a solid choice, especially in existing codebases. Less and Stylus are older preprocessors with similar ideas; Less is still found in some projects (our CSS to LESS tool converts plain CSS).