Sass @use vs @import: Modular Stylesheet Guide
Learn how Sass’s @use rule isolates styles, avoids duplicate code, and lets you configure modules without forking.
22 May 2026, 00:45 UTC

The Problem: Global Namespace Clash
In a growing stylesheet, many teams rely on @import to pull in utility files. Because @import copies the imported file’s contents into every place it’s used, variables, mixins, and functions end up in the global scope. Two different utilities might define a variable named $size, and the later import silently overwrites the earlier one, causing hard‑to‑track visual bugs.
Why @use Solves It
The @use rule treats each Sass file as a module. It loads the module once, makes its members available under a namespace you choose, and does not expose anything unless the author explicitly marks it as public. This gives you encapsulation, predictable dependencies, and a clear way to configure defaults without forking the source.
Namespace and Encapsulation
When you write @use \"utils\"; the members of utils.scss are available under the utils namespace, so you reference them as utils.$variable or @include utils.mixin(). Because each file is compiled only once, even if several stylesheets @use the same module, the CSS output contains a single copy of the generated rules.
Configuration with the with Clause
Module authors can define variables with the !default flag, indicating they are safe to override. Consumers can then supply new values via @use \"utils\" with ($size: 2rem);. The original file stays untouched, and the configuration is applied only to that specific import chain.
Worked Example: Migrating a Button Utility
Suppose you have a utility file _utils.scss that defines a button mixin and a size variable:
/* _utils.scss */
$size: 1rem !default;
@mixin button() {
padding: $size $size * 2;
border-radius: $size;
background: #0069d9;
color: #fff;
}
In a component stylesheet _card.scss you previously wrote:
/* _card.scss (old) */
@import \"utils\";
.card {
@include button();
}
After migrating to @use, the file becomes:
/* _card.scss (new) */
@use \"utils\" as *;
.card {
@include button();
}
If you want to use a larger button just for cards, you can configure the module locally:
/* _card.scss (configured) */
@use \"utils\" with ($size: 1.5rem);
.card {
@include button();
}
Running the Migration
Sass provides a command‑line tool to rewrite @import statements to @use while preserving the compiled CSS. From your project’s root directory, run:
sass migrate --style expanded src/
Where:
- Where to run: Terminal, in the root of the Sass project.
- Permissions: No special rights needed; just read/write access to the source files.
- Placeholders: Replace
src/with the directory that contains your Sass files. - Expected checks: After the migration, run
sass src/styles.scss:dist/styles.cssand verify that the output CSS matches the pre‑migration version (you can diff the two CSS files). - Risks: The tool rewrites files in place; if your project uses libraries that still depend on
@import, you may get duplicate inclusions. Commit your code or back up thesrcfolder before running the migration.
Verifying the Result
To confirm that encapsulation works, compile the migrated stylesheet and inspect the generated CSS:
sass src/styles.scss:dist/styles.css
cat dist/styles.css
You should see the button rules appear exactly once, even if multiple components @use \"utils\". If you notice duplicated rules, check whether any third‑party stylesheet is still using @import \"utils\"; those imports bypass the module system and cause the duplication.
Trade‑off and Limitation
The primary limitation of @use is the need to update every reference to a migrated module. In a large codebase this can be tedious, especially if you rely on the implicit global namespace that @import provided. Teams often mitigate the cost by:
- Running the migration tool on a small subset first and reviewing the diff.
- Adding a temporary
@forwardrule in a compatibility layer that re‑exports the old globals while the migration proceeds.
Another consideration is that libraries that have not adopted @use will still pollute the global scope when you @use them, potentially leading to duplicate code if you also @import the same file elsewhere.
Actionable Closing
Start by picking a single utility file—such as a _utils.scss with variables and mixins—and convert its consumers to @use with an explicit namespace. Run the Sass compiler, check that the CSS output is unchanged, and then move on to the next file. Over time you’ll eliminate global namespace surprises, gain fine‑grained control over what’s public, and have a clear path for configuring modules without forking their source.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.