使用@use规则导入SCSS时如何允许用户自定义覆盖变量
SCSS使用@use无法覆盖变量的解决方案
问题根因
@use 是Sass官方用来替代@import的模块化方案,和@import的全局变量逻辑完全不同,你当前写法失效的原因如下:
@use引入的变量属于模块私有作用域,你在引入后单独声明的同名$width是当前文件局部变量,和原模块的变量完全独立,自然无法覆盖- 原变量文件如果没有加
!default标识,即使传了自定义值也无法覆盖 @use对同一个模块只会加载一次,首次加载后再传参数也不会生效
可行解决方案
方案1:使用@use ... with 官方标准覆盖方式(推荐)
这是Sass官方指定的模块变量覆盖方案,操作步骤如下:
- 首先修改你的原
_variables.scss文件,所有允许用户覆盖的变量都加上!default标识:
// _variables.scss 示例 $width: 200px !default; $primary-color: #1890ff !default; // 其他允许覆盖的变量都按该格式添加!default
- 在用户自定义变量文件中,首次引入变量模块时用
with传入覆盖值:
// user-styles.scss 用户自定义文件 @use "../app/variables" with ( $width: 400px, $primary-color: #f5222d // 其他需要覆盖的变量都写在这里 );
- 确保项目中首次引入
variables模块的位置就是这个用户自定义文件,不要在组件、其他样式文件中提前直接引入原_variables.scss,否则with配置会失效。后续所有需要用到变量的位置,直接引入variables模块就能拿到覆盖后的变量值。
方案2:构建工具全局注入(适合组件库全局覆盖场景)
如果你是做组件库,希望用户不需要手动每个文件引入,可以通过构建工具的预加载配置全局注入覆盖后的变量:
以Vite为例,在vite.config.js中做如下配置:
import { defineConfig } from 'vite' export default defineConfig({ css: { preprocessorOptions: { scss: { // 全局注入带自定义配置的变量模块,as * 表示不需要加命名空间直接使用变量 additionalData: `@use "@/styles/user-styles" as *;` } } } })
Webpack项目可以在sass-loader的additionalData配置项中做相同配置。
常见踩坑说明
- 不要混用
@import和@use,两套体系的变量逻辑不兼容,建议项目全量切换到@use规范 with配置只能在首次引入模块时使用,重复引入模块时添加with会直接抛出编译错误- 不需要覆盖的变量无需写入
with配置,会自动沿用原变量文件的!default默认值
内容的提问来源于stack exchange,提问作者JD Solanki
相关产品推荐
相关产品推荐

