Skip to content

Sass Basics

Before diving into modules, mixins, and architecture, you need a working mental model of what a Sass file actually contains. This lesson walks through the basic building blocks: variables, nesting, partial files, and how Sass output maps back to the CSS you already know.

What Makes Up a Sass File?

A typical .scss file mixes plain CSS declarations with Sass-only features: $variables for reusable values, nested selectors that mirror your HTML structure, @mixin/@include for reusable declaration blocks, and @use to pull in other files.

None of these Sass-only features exist in the compiled output directly, the compiler resolves them at build time and emits plain, browser-ready CSS rules.

// _button.scss
$radius: 8px;

.btn {
  border-radius: $radius;
  padding: 0.6rem 1rem;

  &:hover {
    opacity: 0.9;
  }
}

$radius and the &:hover nested rule are Sass features; the compiled CSS contains only .btn { ... } and .btn:hover { ... }.

Basic SCSS Syntax Rules

selector {
  property: value;

  nested-selector {
    property: value;
  }
}
  • SCSS uses the same curly braces { } and semicolons ; as plain CSS.
  • Variables start with a dollar sign, such as $spacing-md: 1rem;.
  • Nested rules stay inside the parent's curly braces.
  • Line comments // and block comments /* */ are both supported.

Sass Basics Cheatsheet

The everyday syntax you will use in nearly every Sass file.

Concept Example Notes
Variable $gap: 1rem; Reusable named value
Nesting .nav { li { ... } } Compiles to .nav li { ... }
Parent selector &:hover References the enclosing selector
Partial file _variables.scss Leading underscore, not compiled alone
Module load @use 'variables' as v; Imports a partial with a namespace
Mixin @mixin center { ... } Named, reusable declaration block
Include @include center; Applies a mixin's declarations
Line comment // not in output Removed during compilation
Block comment /* kept in output */ Preserved in compiled CSS

Variables at a Glance

Sass variables store a value once and let you reuse it anywhere in the file (or across files, once shared through the module system). This is the single most impactful feature for keeping colors, spacing, and typography consistent.

$primary: #2563eb;
$spacing-md: 1rem;

.alert {
  background: $primary;
  padding: $spacing-md;
}

Nesting at a Glance

Nesting lets you write child selectors inside a parent selector's braces, which visually mirrors your HTML structure and avoids repeating the parent selector for every related rule.

.card {
  padding: 1rem;

  .card-title {
    font-weight: 700;
  }

  &.is-active {
    border-color: blue;
  }
}

Compiles to .card { ... }, .card .card-title { ... }, and .card.is-active { ... }.

Partials and Multiple Files

Real projects split styles across many files, a _variables.scss partial, a _mixins.scss partial, and per-component files, then combine them with @use into one entry stylesheet that gets compiled.

  • Files prefixed with an underscore (_colors.scss) are partials and are never compiled on their own.
  • An entry file like main.scss loads partials with @use './colors';.
  • Only the entry file needs to be passed to the Sass compiler.

Common Mistakes

  • Forgetting the leading underscore on partial files, which causes the compiler to try to build them as separate CSS files.
  • Nesting selectors too many levels deep, producing overly specific and hard-to-override CSS.
  • Using line comments (//) when you actually want the comment to appear in the compiled CSS output.
  • Mixing tabs and spaces inconsistently, which is harmless in SCSS but hurts readability in code review.

Key Takeaways

  • A Sass file combines plain CSS with variables, nesting, mixins, and module loading.
  • Sass-only syntax never reaches the compiled CSS output directly; it is resolved at compile time.
  • Partial files (prefixed with _) organize styles but are not compiled independently.
  • Nesting should mirror your HTML structure without going more than two or three levels deep.

Pro Tip

Keep nesting shallow, if you find yourself nesting more than three levels deep, it usually means the component should be split into smaller pieces or you should lean on the BEM naming convention instead.