SCSS的!default是编译时逻辑,仅影响Sass变量赋值;CSS的var(--x, #000)是运行时行为,浏览器渲染时才解析。二者生命周期不同,不可混用替代。

SCSS里写$color: #007bff !default不等于CSS里var(--color, #007bff)
这是最容易混淆的起点。Sass 的 !default 是编译时逻辑,只在 SCSS 文件被解析那一刻起作用;而 CSS 的 var() 是运行时行为,浏览器在渲染时才去查变量是否存在。两者根本不在同一层——前者决定“生成什么 CSS”,后者决定“生成的 CSS 怎么生效”。
常见错误现象:你在 _variables.scss 里写了 $primary: red !default,又在组件里写了 color: var(--primary, $primary),结果主题切换时颜色不变。问题出在:Sass 把 $primary 编译成了字面量 red,var(--primary, red) 中的 --primary 根本没被 JS 或 :root 设置过,但浏览器照样用 red 渲染——你以为是 fallback,其实是静态回退,完全失去运行时灵活性。
-
!default只对 Sass 变量有效,对 CSS 自定义属性无感知 - 想让 CSS 变量真正可配置,必须把
var()写进最终输出的 CSS,而不是用 Sass 变量“代入”进去 - 若需同时支持编译时默认 + 运行时覆盖,得拆成两层:Sass 层提供基础值(供无 JS 场景兜底),CSS 层用
var()暴露接口
用var(--x, #000)做降级时,为什么默认值有时不触发
不是所有“未定义”都会走默认值。var(--x, #000) 只在 --x **完全未声明**,或被显式设为 initial/unset 时才启用第二个参数。它不关心值是否非法(比如 --x: 123)、也不管父元素有没有继承——这些情况浏览器会尝试解析,失败后可能渲染为 inherited 值,而非跳到默认值。
调试关键点:打开 DevTools → Computed 面板,看目标元素的 color(或其他属性)最终计算值是什么。如果显示 inherit 或空,说明变量链断了,但没走到 var() 默认分支。
立即学习“前端免费学习笔记(深入)”;
- 检查
:root或祖先元素是否真声明了--x;用getComputedStyle(el).getPropertyValue('--x')返回空字符串"",不代表未定义,只代表没找到或值为空 - 避免在默认值里再嵌套
var(--y)却没确保--y存在,否则可能静默失效 - 服务端渲染(SSR)场景下,JS 尚未执行,
:root必须提前注入全部变量,漏一个就是真未定义
React + SCSS 组件中暴露 CSS 变量接口的正确姿势
核心原则:把可配置项从 Sass 变量移到 CSS 自定义属性,用 var() 做桥梁,Sass 只负责组织结构和提供编译时 fallback。
例如在 button.module.scss 中:
.btn {
--_bg: var(--btn-bg, #007bff);
--_color: var(--btn-color, #fff);
--_hover-bg: var(--btn-hover-bg, #0056b3);
background: var(--_bg);
color: var(--_color);
&:hover {
background: var(--_hover-bg);
}
}
这样使用者只需在父容器或 :root 设置 --btn-bg,就能全局/局部覆盖,无需改 SCSS 文件或重新编译。
- 用带下划线前缀(如
--_bg)表明是内部中间变量,避免和用户自定义名冲突 - 不要在 SCSS 中直接
@include或@extend这些变量,它们是纯 CSS 层概念 - 若需兼容老浏览器,可在同一选择器里补一句
background: #007bff;作为 CSS 字面量 fallback
嵌套var()链式降级时如何防循环引用
var(--a, var(--b, red)) 合法,但一旦 --a 和 --b 相互依赖(如 --a: var(--b); --b: var(--a)),Chrome/Firefox 会静默失败,最终属性取初始值(如 color 变成 inherit),不报错也不警告。
这种问题在线上极难定位,尤其当变量分散在多个文件、或通过 JS 动态注入时。
- 禁止在默认值中引用当前变量名:
var(--x, var(--x, black))是典型死循环 - 主题系统中慎用“回退到上一主题变量”,容易在构建阶段就埋下隐式循环
- 用 DevTools 的 Computed 面板逐级点开“used value”,看哪一级返回
inherit或空,快速定位断点
var() 在不同浏览器中对无效值的容忍差异。


















