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;
}
$variablesare 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:
&--largebecame.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);
}
@useloads Sass modules (built-ins likesass:math, or your own files, which are namespaced by file name). The older@importrule is deprecated in Sass and will be removed.@functionreturns a value;@mixin+@includeinserts declarations.- In Sass,
/is not division — usemath.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).