Sass Variables & Nesting
Sass variables: $variable
A Sass variable is declared with a leading dollar sign and can hold any Sass value — a color, a number, a string, a list, or a map.
$brand-color: #0066cc;
$spacing-unit: 8px;
$font-stack: 'Helvetica Neue', Arial, sans-serif;
.button {
background: $brand-color;
padding: $spacing-unit * 2;
font-family: $font-stack;
}Once compiled, every reference to the variable is replaced with its literal value — the browser only ever sees the final numbers and colors, with no trace of the variable name left behind.
/* Compiled output */
.button {
background: #0066cc;
padding: 16px;
font-family: 'Helvetica Neue', Arial, sans-serif;
}Sass variables vs. CSS custom properties
--variable), but the two work at fundamentally different times and have very different capabilities.Sass | CSS | |
|---|---|---|
When it exists | Only at compile time — resolved away entirely before the browser sees the CSS. | At runtime, in the browser — a real, live value the page can read and change. |
Can it change via JavaScript? | No — there is nothing left to change once compilation has happened. | Yes — |
Can it change per media query / breakpoint? | No — a single compiled value is baked into the output for a given selector. | Yes — redeclaring it inside a |
Scope | Sass scoping rules (roughly block-scoped, depending on where declared). | Follows the CSS cascade and inheritance, scoped to the elements it is declared on. |
Nesting selectors
.card {
padding: 1rem;
border: 1px solid #ddd;
.card-title {
font-size: 1.25rem;
font-weight: 600;
}
.card-body {
color: #555;
}
}which compiles to:
.card {
padding: 1rem;
border: 1px solid #ddd;
}
.card .card-title {
font-size: 1.25rem;
font-weight: 600;
}
.card .card-body {
color: #555;
}The & parent selector
& refers back to the parent selector, which is essential for attaching a pseudo-class, pseudo-element, or a modifier class directly to the parent rather than selecting a descendant of it..button {
background: #0066cc;
color: white;
&:hover {
background: #0052a3;
}
&.is-disabled {
opacity: 0.5;
}
// BEM-style modifier built with & and string interpolation
&--large {
padding: 1rem 2rem;
font-size: 1.125rem;
}
}compiles to:
.button {
background: #0066cc;
color: white;
}
.button:hover {
background: #0052a3;
}
.button.is-disabled {
opacity: 0.5;
}
.button--large {
padding: 1rem 2rem;
font-size: 1.125rem;
}&--large or interpolated names built with #{$variable}, patterns native CSS nesting has no equivalent for. See CSS Nesting for a direct comparison of where the two diverge.Putting it together
$border-radius: 8px;
$muted-text: #6b7280;
.card {
padding: 1rem;
border-radius: $border-radius;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
&__title {
font-weight: 600;
}
&__meta {
color: $muted-text;
font-size: 0.875rem;
}
&:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
}$variable: value;declares a compile-time value, resolved and inlined before shipping.Nesting mirrors HTML structure visually, but every level compiles to a fully qualified flat selector.
&stands in for the parent selector wherever it appears — directly attached, or combined with a suffix for BEM-style modifiers.