Skip to content

Sass Performance

Sass performance has two dimensions: how fast your files compile, and how large and efficient the resulting CSS is. This lesson covers practical techniques for improving both, especially in larger projects.

Two Kinds of Sass Performance

Compile-time performance is about how quickly the Sass compiler processes your files, this rarely matters for small projects but can add up in large codebases with many partials. Output performance is about the size and efficiency of the generated CSS the browser actually has to parse and apply.

sass --style=compressed src/main.scss dist/main.css

Always compile with --style=compressed for production; it removes whitespace and comments, directly reducing the CSS file size shipped to users.

Quick Performance Checklist

1. Use @use, not @import (loads each file once)
2. Compile with --style=compressed for production
3. Audit loops for excessive generated CSS
4. Prefer placeholders + @extend over unparameterized mixins for pure reuse
5. Avoid deeply nested selectors that bloat specificity and size
  • The module system (@use) avoids the duplicate-loading performance cost of @import.
  • Compressed output directly reduces file size, which affects download and parse time in the browser.
  • Loops (@each, @for) can silently generate far more CSS than intended if not checked against the compiled output.
  • Deep nesting increases both selector specificity and the raw size of the compiled CSS.

Sass Performance Cheatsheet

Common performance levers and their impact.

Technique Impact Notes
@use over @import Faster compiles, no duplicate loading Also solves namespacing issues
--style=compressed Smaller shipped CSS Always use for production builds
Auditing loop output Prevents CSS bloat Read the actual compiled CSS, not just the SCSS
Placeholders over mixins Smaller output for unparameterized reuse Only for styles with no variation
Shallow nesting Smaller, less specific selectors Keep to ~3 levels or fewer
Source maps in dev only Faster production builds Disable or strip for the final shipped build

Compile-Time Performance

For most projects, compile time is a non-issue. In genuinely large codebases (hundreds of partials), switching from @import to @use helps, since @use guarantees each file is only processed once, no matter how many other files reference it.

Reducing Output CSS Size

The biggest, most common source of unnecessary output size is unaudited loops, a @for or @each generating far more rules than the project actually uses, and unused CSS shipped simply because it was never removed after a design changed.

// Before: generates 100 unused utility classes
@for $i from 1 through 100 {
  .m-#{$i} {
    margin: $i * 1px;
  }
}

// After: generates only the steps the design system actually uses
$spacers: 0, 4, 8, 16, 24, 32, 48, 64;
@each $space in $spacers {
  .m-#{$space} {
    margin: $space * 1px;
  }
}

@extend vs Mixin Output Size, Revisited

As covered in the @extend lesson, placeholders shared through @extend avoid duplicating declarations across every call site, which can meaningfully reduce output size for widely reused, unparameterized style groups in a large component library.

Common Mistakes

  • Never actually inspecting the compiled CSS output, missing loops or mixins that generate far more CSS than intended.
  • Continuing to use @import in a large project instead of migrating to @use for its one-time-loading guarantee.
  • Shipping uncompressed, unminified CSS to production instead of using --style=compressed.
  • Nesting selectors deeply, which increases both specificity and the raw size of every generated rule.

Key Takeaways

  • Sass performance has two dimensions: compile-time speed and the size/efficiency of the output CSS.
  • @use improves compile performance over @import by loading each file only once.
  • Always ship compressed CSS to production using --style=compressed.
  • Regularly audit loop-generated CSS and deeply nested selectors for unnecessary bloat.

Pro Tip

Periodically diff your compiled CSS's file size and rule count against a previous build, a sudden, unexplained jump is often the first sign that a loop, mixin, or nesting pattern started generating far more CSS than intended.