Choosing Between @import and @use in Sass: A Migration Decision Guide
A practical decision guide for migrating from Sass @import to @use: constraints, trade-offs, a side-by-side comparison table, and a validated migration example with namespace aliases and @forward.
09 Mar 2026, 10:04 UTC

The Decision You Face
If you maintain a Sass codebase, you have likely encountered the deprecation warning for @import. The Sass team has marked @import for removal in a future major release, and Dart Sass 1.23+ introduced @use as its replacement. The choice is not merely syntactic: @import injects a file's contents into the global scope on every invocation, while @use loads a module once, creates a namespaced scope, and prevents variable and mixin collisions. This guide helps you decide when to migrate, how to handle mixed codebases, and what constraints to verify before flipping the switch.
Constraints That Shape the Decision
- Sass implementation version:
@userequires Dart Sass ≥ 1.23. If your build pipeline pins an older version (or uses the deprecated LibSass), you must upgrade first. - Plain CSS imports:
@usecannot import.cssfiles. You must keep@importfor those or rename them to.scss. - Legacy dependencies: Third‑party libraries that still use
@importinternally will not work with@useunless they are refactored or you shim them. - Team familiarity: Namespaced access (
colors.$primary) changes how developers write mixins and variables. Budget time for onboarding.
Quick Comparison
| Behavior | @import (legacy) | @use (module system) |
|---|---|---|
| Scope | Global — every variable, mixin, function leaks into the importing file | Namespaced — members accessed via namespace.$var or @include namespace.mixin |
| Duplicate loading | File re‑evaluated on each @import; can emit duplicate CSS | Loaded once per compilation; subsequent @use references the same module instance |
| Aliasing | Not supported | Supported: @use 'tokens' as t; |
| Re‑export | Implicit — everything becomes globally available | Explicit via @forward; enables curated public APIs |
| Plain CSS files | Supported | Not supported |
| Deprecation status | Marked for removal in next major Dart Sass release | Stable, recommended for all new code |
Trade‑offs in Practice
When to Migrate Now
- New projects or greenfield components — start with
@useto avoid technical debt. - Codebases suffering from variable name collisions (e.g., two partials defining
$spacing). - Teams building a shared design‑token library;
@forwardlets you publish a clean API.
When to Delay
- Large legacy codebases where a full rewrite would block feature work. Incremental migration is possible but requires discipline.
- Projects that must import vendor
.cssfiles directly and cannot rename them. - Environments locked to LibSass or Dart Sass < 1.23 with no upgrade path.
Concrete Migration Example
Assume a tokens partial and a component that consumes it.
Before: @import (global scope)
// _tokens.scss
$primary: #2a7ae2;
$spacing: 1rem;
@mixin card {
padding: $spacing;
border: 1px solid $primary;
}
// button.scss
@import 'tokens';
.btn {
@include card;
background: $primary;
}
Compiling button.scss works, but if another file also @import 'tokens' and defines its own $primary, the last import wins — silently.
After: @use with namespace
// _tokens.scss (unchanged)
$primary: #2a7ae2;
$spacing: 1rem;
@mixin card {
padding: $spacing;
border: 1px solid $primary;
}
// button.scss
@use 'tokens' as t;
.btn {
@include t.card;
background: t.$primary;
}
Now t.$primary is unambiguous. If a second component also @use 'tokens' as t;, both read the same module instance — no duplicate CSS, no variable clobbering.
Adding a Public API with @forward
If _tokens.scss is part of a shared package, expose only what consumers need:
// _tokens.scss
$primary: #2a7ae2;
$spacing: 1rem;
@mixin card { ... }
// _index.scss (package entry point)
@forward 'tokens' show $primary, $spacing, card;
// consumer.scss
@use 'pkg' as design;
.box { background: design.$primary; }
Consumers see a curated namespace; internal helpers stay private.
Validation Steps You Can Run Today
- Create a test module:
echo "$primary: #336699; @mixin theme { color: $primary; }" > colors.scss - Write a consumer using
@use:
echo "@use 'colors'; .btn { @include colors.theme; }" > main.scss - Compile with Dart Sass ≥ 1.23:
sass main.scss output.css - Inspect
output.css— you should see exactly one.btn { color: #336699; }rule. - Repeat with
@import 'colors';and invoke the mixin twice; the rule appears twice, demonstrating duplicate emission. - Run
sass --watch main.scss output.cssto verify live reload works with@use.
If any step fails, check your Sass version (sass --version) and ensure no .css files are being @used.
Limitations and Gotchas
- Mixed
@import/@usein one file can produce duplicate CSS and unpredictable namespace behavior. Pick one per entry point. - Private members (prefixed with
-or_) are not forwarded automatically; you must@forwardthem explicitly if needed. - Dynamic imports (interpolation in the path) are not supported by
@use; you must know the module path at compile time. - Build tool plugins (webpack
sass-loader, Vite, etc.) must be configured to use Dart Sass. Some default to the legacy implementation.
Rollback Plan (If You Must)
Because @use changes the generated CSS only when namespaces prevent duplication, rolling back is a matter of reverting the source files and recompiling. No runtime state changes. Keep the @import version in git history until the new output passes visual regression tests.
Final Checklist Before Committing
- All entry points compile with
sass --no-source-map --style=compressedand produce identical visual output. - No
@importstatements remain in files that also contain@use. - Plain CSS imports are either renamed to
.scssor kept as@importin a dedicated legacy entry point. - Team members can write
namespace.$varand@include namespace.mixinwithout errors. - CI runs the validation steps above on every pull request.
Once the checklist passes, you can safely delete the deprecation warnings from your build logs and treat @use as the standard for the project.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.