Professional CSS WorkflowPro· 50 min read

Sass / SCSS: The CSS Preprocessor

Sass is CSS with superpowers — variables, nesting, reusable mixins and the ability to split your styles into many small files. The best-selling paid CSS courses are built on it, and many real codebases still expect it.

What you will learn

  • Explain what a preprocessor is and why Sass exists
  • Use variables, nesting, partials and @use
  • Write a reusable mixin and use @extend

What is a preprocessor?

A browser only understands plain CSS — it has never heard of Sass. So Sass is a language you write, then a tool compiles it into normal CSS that the browser can read. That compile step is why Sass is called a preprocessor: it runs before the CSS reaches the browser.

Sass (Syntactically Awesome Style Sheets) gives you tools plain CSS historically lacked: real variables, nesting, reusable chunks called mixins, math, and the ability to split styles across many files. The modern, CSS-like syntax uses the .scss file extension (the one everyone uses today), so people say “Sass” and “SCSS” to mean the same thing.

Note: Because Sass needs compiling, its code does not run live in the browser preview — so the examples below are marked as Sass input with the plain CSS they produce shown as an Output note. You compile it with a tool (covered at the end).

Variables and nesting

Sass variables start with a $. Nesting lets you write child rules inside a parent, just like the native nesting you saw earlier. Here is some SCSS:

SCSS: variables ($) and nesting
// styles.scss  (Sass input — gets compiled to CSS)
$brand: #4338ca;
$radius: 12px;

.card {
  border: 1px solid #e6e8f0;
  border-radius: $radius;
  padding: 16px;

  h3 { color: $brand; }      // becomes .card h3
  &:hover { box-shadow: 0 10px 24px rgba(20,24,48,.12); }  // becomes .card:hover
}

Read it piece by piece:

  • $brand and $radius are Sass variables — named values you set once and reuse. (Sass also predates CSS variables, which is why older codebases use $ heavily.)
  • The h3 { ... } rule is nested inside .card, so it compiles to .card h3.
  • &:hover uses & (“the current selector”) to compile to .card:hover — exactly like native nesting.
Output: the plain CSS Sass generates
/* The compiled CSS the browser actually receives */
.card { border: 1px solid #e6e8f0; border-radius: 12px; padding: 16px; }
.card h3 { color: #4338ca; }
.card:hover { box-shadow: 0 10px 24px rgba(20,24,48,.12); }

Notice the variables are gone — Sass has substituted their values ($radius became 12px, $brand became #4338ca) — and the nesting has been flattened into ordinary descendant selectors. This compiled CSS is what the browser loads.

Mixins — reusable blocks of CSS

A mixin is a named, reusable group of declarations — like a function for CSS. You define it once with @mixin and drop it into any rule with @include. It can even take parameters. This is the single most loved Sass feature:

SCSS: a parameterised mixin
// Define a reusable mixin (it can take arguments)
@mixin flex-center($gap: 0) {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: $gap;
}

.hero   { @include flex-center(12px); height: 200px; }
.toolbar { @include flex-center; }

The @mixin flex-center($gap: 0) bundles the three-line flexbox-centring recipe (which you learned by hand in the Centering lesson) into one reusable name, with a $gap argument that defaults to 0. Then @include flex-center(12px) pastes those declarations in with a 12px gap, and @include flex-center pastes them with the default gap. Here is what it compiles to:

Output: each @include is expanded inline
/* Compiled output — the mixin is expanded into each rule */
.hero    { display: flex; justify-content: center; align-items: center; gap: 12px; height: 200px; }
.toolbar { display: flex; justify-content: center; align-items: center; gap: 0; }

The mixin’s declarations have been copied into each rule that included it, with the argument filled in. Write the centring recipe once, reuse it anywhere — and if you improve the mixin, every place that includes it updates.

Partials and @use — splitting your CSS into files

Big stylesheets get unwieldy. Sass lets you split CSS into small files called partials (their names start with an underscore, like _buttons.scss) and then pull them together. The modern way to combine files is the @use rule. The process:

  1. Create small partials, each for one concern: _variables.scss, _buttons.scss, _cards.scss.
  2. In a main file (main.scss), bring them in with @use: for example @use "buttons"; and @use "cards";.
  3. Compile main.scss — Sass stitches every partial into one CSS file the browser loads.
  4. (@use is the modern replacement for the older @import, which Sass is phasing out.)

@extend — share a base style

@extend lets one selector inherit another’s rules, so related components share a base without repeating it:

SCSS: @extend shares a common base
%card-base {                 // a "placeholder" base, only used via @extend
  border-radius: 12px; padding: 16px; background: #fff;
}
.product-card { @extend %card-base; border: 1px solid #e6e8f0; }
.alert-card   { @extend %card-base; border: 1px solid #fca5a5; }

The %card-base is a placeholder — a base set of rules that only appears in the output if something extends it. Both .product-card and .alert-card use @extend %card-base to inherit the shared radius, padding and background, then add their own border. This keeps the common look in one place. The compiled CSS groups the shared selectors together so the base declarations are written only once.

Tip: To actually compile Sass, the common tools are the Sass CLI (run sass styles.scss styles.css in a terminal) or a build tool like Vite, which compiles .scss automatically. You will set this up in the next lesson on build tooling, or your framework handles it for you.

Q. Why does Sass need a compile step before the browser can use it?

Answer: Sass is a preprocessor: you write SCSS, and a tool compiles it into the plain CSS that browsers actually understand.

✍️ Practice

  1. Write an SCSS file with a $brand variable, a nested .card rule, and compile it (or trace by hand) to the plain CSS it produces.
  2. Create a @mixin for a button style that takes a colour argument, and @include it for two different buttons.

🏠 Homework

  1. Refactor one project’s CSS into SCSS: pull colours into $ variables, nest each component, and split buttons and cards into partials combined with @use.
Want to learn this with a mentor?

CodingClave runs guided, project-based training (28-day, 45-day & 6-month batches).

Explore Training →