Skip to content

Sass Modules

Sass modules are the modern way to split a project across files and load them safely, with namespacing that prevents naming collisions between unrelated files. This lesson introduces the module system before diving deeper into @use, @forward, and @import in the following lessons.

What Is the Sass Module System?

The module system, introduced with @use and @forward, replaced the older, global @import rule. Each file loaded with @use becomes its own module: its variables, mixins, and functions are namespaced instead of dumped into one shared global scope.

This solves a real problem with @import: two files could accidentally define a variable with the same name, and whichever was imported last would silently win, causing hard-to-trace bugs.

// _colors.scss
$primary: #2563eb;

// main.scss
@use 'colors';

.button {
  background: colors.$primary;
}

The colors. namespace makes it explicit exactly which file $primary came from, eliminating naming collisions.

Module Loading Syntax

@use 'path/to/file';
@use 'path/to/file' as alias;
@use 'path/to/file' as *;
@forward 'path/to/file';
  • @use loads a file once and exposes its members through a namespace based on the filename.
  • as alias lets you rename the default namespace to something shorter or clearer.
  • as * removes the namespace entirely (use sparingly, it can cause the same collisions @use was designed to prevent).
  • @forward re-exports another file's members so they are available to whoever loads your file.

Sass Modules Cheatsheet

The core module system commands you'll use to structure any real project.

Rule Example Effect
Load a module @use 'colors'; Namespace defaults to the filename: colors.
Custom namespace @use 'colors' as c; Access members as c.$primary
No namespace @use 'colors' as *; Access members directly, no prefix
Re-export @forward 'colors'; Passes members through to consumers of this file
Built-in module @use 'sass:math'; Loads a Sass built-in module
Load once @use (always) Sass loads each file only once, no matter how many times it's used
Legacy loading @import 'colors'; Deprecated global import, avoid in new code

Namespacing Explained

By default, @use 'buttons'; creates a namespace matching the filename (without the underscore or extension): buttons. Every variable, mixin, and function from that file must be accessed with the buttons. prefix.

// _spacing.scss
$gap: 1rem;
@mixin stack($space: $gap) {
  display: flex;
  flex-direction: column;
  gap: $space;
}

// main.scss
@use 'spacing';

.list {
  @include spacing.stack(1.5rem);
}

Each Module Is Loaded Only Once

Unlike @import, which re-executes a file's code every time it's imported (duplicating output CSS if a file contains actual style rules), @use loads a given file only once no matter how many other files load it.

  • Prevents duplicated CSS output from a partial being loaded multiple times through different paths.
  • Prevents duplicated variable or mixin definitions from causing conflicting behavior.
  • Makes dependency graphs predictable, since load order can't cause a file to run twice.

Modules vs the Legacy @import Rule

The old @import rule shared everything globally with no namespacing, was deprecated by the Sass team, and is planned for eventual removal from the language. All new Sass code should use @use and @forward instead.

Aspect @import (legacy) @use / @forward (modern)
Namespacing None, global scope Required by default, prevents collisions
Loaded multiple times Re-runs every time Loaded once, regardless of how many @uses
Status Deprecated Recommended, actively developed
Private members Not supported Supported via leading underscore names

Common Mistakes

  • Continuing to use @import in new projects instead of adopting @use and @forward.
  • Using as * by default, which removes namespacing and reintroduces the exact collision risk modules were built to prevent.
  • Assuming @use-ing the same file twice from different paths loads it twice; Sass deduplicates by resolved file path.
  • Forgetting the namespace prefix when accessing a loaded module's variables, mixins, or functions.

Key Takeaways

  • The Sass module system (@use/@forward) replaced the legacy, global @import rule.
  • Every @used file gets a namespace, preventing naming collisions between unrelated files.
  • Sass loads each unique module only once, no matter how many files reference it.
  • Prefer explicit or aliased namespaces over as * to keep the origin of variables and mixins clear.

Pro Tip

When a namespace name feels too long to type repeatedly, alias it with as (@use 'design-tokens' as tokens;) instead of dropping it entirely with as *, you keep clarity with less typing.