Sass Modules, Partials, and Scalable Architecture
Organize large Sass codebases using partial files, @use, @forward, module namespaces, explicit configuration, and layered stylesheet architecture.
Partials, Entry Points, and File Organization
A partial is a Sass source file intended to be loaded by another stylesheet rather than compiled as an independent entry point. Partial filenames conventionally begin with an underscore, such as _variables.scss or _buttons.scss.
A project may separate tokens, functions, mixins, base styles, layouts, components, and utilities into focused files. A small number of well-defined entry points can then compose the required modules.
Avoid creating a file for every trivial declaration. File boundaries should communicate architectural responsibility and make ownership clear.
A typical structure might look like this:
src/scss/
abstracts/
_tokens.scss
_functions.scss
_mixins.scss
base/
_reset.scss
_typography.scss
components/
_buttons.scss
_cards.scss
layout/
_header.scss
_grid.scss
main.scss
The underscore is a naming convention associated with Sass partials. A module is loaded through Sass's module resolution rules, and the importing file's path is resolved relative to the configured load paths.
What is the conventional purpose of an underscore-prefixed Sass partial?
The Modern @use Module System
The @use rule loads a Sass module and exposes its public members through a namespace. This makes dependencies explicit and helps prevent accidental name collisions.
For example, @use "abstracts/tokens"; loads a module whose variables can be accessed through the tokens namespace. The consuming file can then reference tokens.$brand-color.
Use as to select an alias or as * to remove the namespace. Although as * can shorten names, it can also reintroduce naming collisions and hide dependencies. Explicit namespaces are generally easier to maintain in large projects.
Sass modules are loaded once within the module system, so repeated references to the same module do not behave like repeated textual concatenation of the source file.
// abstracts/_tokens.scss
$brand-color: #5b5bd6;
$spacing-md: 1rem;
// abstracts/_mixins.scss
@mixin flex-center {
display: flex;
align-items: center;
justify-content: center;
}
// main.scss
@use "abstracts/tokens";
@use "abstracts/mixins";
.hero {
padding: tokens.$spacing-md;
background: tokens.$brand-color;
@include mixins.flex-center;
}@use statements belong at the beginning of the consuming stylesheet, before ordinary style rules.How does `@use "abstracts/tokens";` expose a public variable by default?
The @forward Rule and Public Module APIs
The @forward rule re-exports members from another Sass module. It allows a directory or package to provide a centralized entry point instead of requiring every consumer to know the location of each internal file.
For example, an abstracts directory can forward its tokens, functions, and mixins through a single _index.scss file. Consumers then load the index module and access the exposed API through one namespace.
The show and hide options can control which members are re-exported. The as option can rename forwarded members. These capabilities help establish a deliberate public API for a shared design system.
Forwarding is especially useful for Sass libraries, component systems, and multi-package repositories. Internal implementation files can change while consumers continue using the public entry point.
Expose stable tokens and reusable functions intentionally. Keep implementation-specific members private when they are not meant to be consumed outside the module.
// abstracts/_index.scss
@forward "tokens";
@forward "functions";
@forward "mixins";
// main.scss
@use "abstracts" as ui;
.page {
color: ui.$brand-color;
padding: ui.spacing(4);
}ui namespace.
The spacing() function must be defined in the forwarded functions module, and $brand-color must be defined in the forwarded token module. File names and directory structure must match the module paths.What is the primary purpose of `@forward`?
Module Configuration and Theme Overrides
Sass modules can expose configurable variables by declaring defaults with !default. Consumers can configure those variables when loading a module with @use and a with clause.
This approach is useful for white-label applications, component libraries, and design systems that allow a consumer to override approved brand tokens.
Module configuration must occur when the module is first loaded. A module cannot be independently configured multiple times with conflicting configurations within the same compilation context.
Keep configurable values focused on stable customization points. Exposing every internal variable makes the module's public API difficult to maintain.
// themes/_theme.scss
$brand-color: #5b5bd6 !default;
$surface-color: #ffffff !default;
$text-color: #222222 !default;
.button {
background: $brand-color;
color: white;
}
// customer.scss
@use "themes/theme" with (
$brand-color: #00695c,
$surface-color: #f5f5f5,
$text-color: #202020
);Which Sass feature allows consumers to configure eligible module variables when loading a module?