!default不生效是因为变量已被提前定义,仅在Sass首次解析该变量名时赋值;常见原因包括UI库(如element-plus)提前声明、Vite的additionalData注入、@use模块未声明!default、:root中未用#{}插值。

!default 不是“设个默认值就完事”,而是构建可定制 CSS 库的编译期守门人——它只在变量第一次被声明时生效,一旦错过时机,后续所有覆盖尝试都静默失效。
为什么 $color-primary: #007bff !default 总不生效
根本原因不是语法写错,而是 Sass 已经在别处提前绑定了 $color-primary。常见位置包括:node_modules/element-plus/theme-chalk/src/common/var.scss、Vite 的 css.preprocessorOptions.sass.additionalData 注入、甚至 uni-app 自动加载的 uni.scss。
- 用 VS Code 全局搜索
$color-primary:,重点排查node_modules/下 UI 库的变量文件 - 运行
grep -r "\$color-primary:" src/ node_modules/(macOS/Linux)确认真实加载顺序 - 检查 vite.config.ts 中
additionalData是否注入了同名变量——它比你任何@use都早执行 - 避免在同一个文件里先写
$color-primary: red;,再写$color-primary: blue !default;(语法合法但无效)
@use 场景下 with 子句报 “This variable was not declared with !default”
这是 @use 的硬性约束:外部想用 with ($spacing: 1.5rem) 覆盖,源模块里必须显式写 $spacing: 1rem !default;。没加 !default 的变量,@use 默认视为私有常量,禁止覆盖。
- 错误写法:
$border-radius: 6px;→ 外部@use "vars" with ($border-radius: 8px)直接报错 - 正确写法:
$border-radius: 6px !default;→ 覆盖才被允许 - 若需跨模块共享且支持覆盖,考虑
@forward "vars" with ($border-radius: 8px !default)组合 - 别在
with里传源模块根本不存在的变量名,比如$font-size在 vars.scss 里压根没定义,也会报错
:root 里导出 CSS 变量时 $primary 不生效
SCSS 变量不能直接出现在 CSS 自定义属性的值位置,--color: $primary; 会被原样输出为字面字符串,最终生成无效 CSS。
立即学习“前端免费学习笔记(深入)”;
- 必须用插值:
--color: #{$primary}; - 计算函数也要包住:
--bg-light: #{lighten($primary, 10%)} -
!default对--xxx完全无效——那是运行时逻辑,得靠var(--color, #333)实现兜底 - 别写
$--color: #fff !default;,SCSS 不允许--开头的变量名,会编译失败
真正难的是让每个新增组件都走通这条链路
不是第一次写对 @use 就算成功。每次加一个新组件,都要确保:_index.scss 显式收口 → @forward 带 as 命名空间 → 变量严格分层(原子 → 语义 → 组件)→ 所有可覆盖变量带 !default → 用户主题文件必须在所有组件 @use 之前加载。
松动一次,模块边界就从代码里消失,变成靠文档和人肉记忆维系的脆弱约定。最隐蔽的坑,往往藏在构建流程里:Vite 的 additionalData、UI 库的自动 @import、框架的全局 uni.scss 加载机制,三者叠加后,你改的那行 !default 可能连编译器的“第一次见到”都排不上队。


















