@import has been officially deprecated in Dart Sass since version 1.80.0, released in October 2024. The Sass team has said it won't release Dart Sass 3.0.0, the version that removes it, until at least two years later. That means no earlier than October 2026. You can ignore the warning for now, but if you haven't rewritten your import graph by the time 3.0.0 arrives, the compiler will treat @import as a literal CSS directive instead of a Sass rule, and your build will break. This takes more than replacing one keyword across your codebase. You need to rethink how shared variables, mixins, and design tokens move through your stylesheets.
- Deprecation status:
@importhas been deprecated since Dart Sass 1.80.0 (October 2024). - Final removal target: Dart Sass 3.0.0, no earlier than two years after 1.80.0, or October 2026.
@use/@forwardsupport: available since Dart Sass 1.23.0 (2019), so you can start migrating now.- Migration CLI:
sass-migrator(npm install -g sass-migrator, then run it withnpxor the global binary). - Core logic:
@useloads members into an isolated namespace.@forwardexposes members to other files as part of an API. - Bundler impact: Webpack and Vite users need to update their aliases to match the new module resolution paths.
- On
node-sass: this particular deprecation won't affect you, but that doesn't mean you're in the clear.node-sasswraps the older, already deprecated LibSass engine, which never implemented the module system. If you're still using it, moving to Dart Sass should come first.
Why Is Sass @import Actually Being Deprecated?
The legacy @import rule was designed to resemble standard CSS, but it gave developers a global scope problem. Whenever you imported a file, its variables, mixins, and functions became available to everything compiled after it. Finding where a particular $brand-primary variable was defined could mean searching the entire codebase.
Library authors worked around name collisions by adding long prefixes to everything, even when those names were awkward to use.
Performance suffered too. If five components used @import "buttons", Sass could compile the button styles five times, once for each importing file. The output from a shared partial could grow with every file that loaded it. Scope problems can also cause stubborn CSS bugs, such as a box-shadow that silently refuses to render because an inherited rule higher up the cascade overrides it.
The Real Consequence: What Happens If You Don't Migrate?
It's easy to assume that leaving legacy code alone means putting up with a console warning. The consequences go further. Dart Sass is moving toward treating @import the way standard CSS does: as a browser directive for fetching an external stylesheet.
When Dart Sass 3.0 removes support for Sass's implementation of @import, the compiler will stop pulling _variables.scss or _mixins.scss partials into your main bundle. Instead, it will write a literal @import url('_variables.scss'); into the compiled CSS.
The browser will then try to fetch a .scss file that doesn't exist on your production server, and the import will fail silently. Variables, mixins, and functions that depended on that partial will no longer be available, so the declarations that use them may disappear or produce invalid CSS. Your layout can break wherever those styles mattered.
Many migration guides give this consequence little attention.
The Core Rule: When to Reach for @use vs @forward
The tricky part of this migration is knowing which new rule belongs in which file. Think about what the file is meant to do.
Use @use for Application Logic
Use @use when a file needs variables, mixins, or functions to produce CSS. This usually means a component stylesheet.
Loading a file with @use 'colors'; creates a namespace based on its file name. You then access variables as color: colors.$primary;. Their scope stays local to the component.
Rely on @forward for Shared Libraries
Use @forward for an index file or shared library file that passes variables and mixins on to other files. It provides a central route to those members.
If your design tokens live in fifteen files, you don't want every component to @use each one. Create a central _index.scss that forwards the individual partials instead. Files that load the index can access all the forwarded members through it.
Step-by-Step Migration and Fixing Broken Builds
Running the Automated sass-migrator
The Sass team provides an official CLI to handle much of the conversion. If npx gives you version errors, first check that your Node.js install is current. Run the tool against your main entry point so it can follow the dependency tree:
npx sass-migrator module --migrate-deps src/styles/main.scss
It can rewrite basic imports and add namespaces, but complex legacy codebases often need manual fixes before they build again.
Troubleshooting "Declaration Order" Errors
A common error after running the migrator involves declaration order. Under the old system, you could put an @import statement almost anywhere in a file, including inside a selector.
The module system doesn't allow that and reports an error:
Error: @use rules must be written before any other rules.
Every @use and @forward rule must be at the very top of the file, before any CSS rule, variable, or mixin definition. If the migrator can't extract a nested import, move it to the top yourself and adjust the surrounding scope.
Resolving Shared Variable Collisions
In the @import era, you could override a library's default by defining a variable before importing the library. The module system doesn't accept that implicit override and reports an error instead:
Error: This variable was not declared with !default in the @used module.
To configure a module, pass overrides explicitly with the with keyword. If the migrator doesn't preserve your theme overrides, rewrite the import like this:
@use 'library' with (
$primary-color: #ff0000,
$border-radius: 4px
);
A Modern Architecture: Structuring Design Tokens with @forward
To make the module system useful, give your design tokens a central API. Create a tokens directory for the raw values: _colors.scss, _typography.scss, and _spacing.scss.
Add an _index.scss file inside that directory. Use @forward there to bring the tokens together and prefix them so their names stay clear when other files consume them:
// tokens/_index.scss
@forward 'colors' as color-*;
@forward 'typography' as font-*;
@forward 'spacing' as space-*;
Each component then needs just one @use statement. The prefixes keep variable names readable and help prevent collisions:
// components/_button.scss
@use '../tokens';
.btn {
background-color: tokens.$color-primary;
padding: tokens.$space-medium;
}
Handling Path Resolution in Bundlers
Moving from @import to @use can break path resolution in bundlers such as Vite and Webpack. If you used includePaths in your Sass loader config to avoid long relative paths like ../../../styles/variables, you'll need to update that setup.
Modern Dart Sass supports the pkg: URL scheme, and bundler aliases can keep paths short. Vite's built-in alias resolution works with @use once vite.config.js points to the styling directory:
resolve: {
alias: {
'@styles': path.resolve(__dirname, './src/styles')
}
}
You can then write @use '@styles/tokens'; from anywhere in the project without relying on fragile relative paths. After migrating, add the stylelint rule at-rule-disallowed-list: ['import'] to your CI pipeline so a legacy @import doesn't slip back in.
