CSS变量回退机制依赖var()第二个参数,仅在变量未声明或值为initial/inherit/unset时生效;空字符串被视为有效值,不触发回退;支持嵌套var()实现多级降级,但需避免循环引用。

直接用 var() 的第二个参数,不是给变量本身设默认值,而是给引用处加 fallback。 CSS 变量(--my-var)本身不支持“定义时自带默认值”,但每次调用它时,var(--my-var, #000) 这种写法才是真正的、规范级的回退机制——浏览器原生支持,无需 polyfill,也不依赖 JavaScript。
var() 的第二个参数什么时候生效
只在两种情况下触发回退:
-
--my-var完全未在任何作用域中声明(比如漏写了:root { --my-var: red; }) -
--my-var被显式设为initial、inherit或unset(注意:""空字符串 ≠ 未定义,它会被当作有效值取用)
常见错误是把 --size: "" 当作“清空变量”,结果 font-size: var(--size, 16px) 实际取到的是空字符串,导致该属性被忽略,退成浏览器默认字号。这不是回退没生效,而是变量“已定义”,只是值为空。
多级回退:用嵌套 var() 构建降级链
回退值本身可以再是 var(),形成优先级链条,适合主题系统或跨组件复用场景:
立即学习“前端免费学习笔记(深入)”;
body {
background-color: var(--bg-color, var(--fallback-bg, #fff));
}执行顺序是:先查 --bg-color → 未定义则查 --fallback-bg → 再未定义才用 #fff。这种写法在 Sonner、Font Awesome 7 的主题变量中很常见,但要注意避免循环引用,比如 var(--a, var(--b, var(--a, black))) 会出问题。
和 @supports 混用不可靠,别依赖它检测变量支持
@supports (color: var(--x)) 在多数浏览器中返回 true,即使变量根本不存在——因为语法合法,只是运行时才求值。所以不能靠它做 CSS 变量可用性判断。
真正需要兼容旧浏览器(如 IE)时,应该用传统属性 + var() 叠加写法:
.icon {
font-family: "Font Awesome 7 Free", sans-serif;
font-family: var(--fa-family-classic), sans-serif;
}前一行是回退,后一行是变量引用。这样即使不支持 CSS 变量,也能保底显示字体图标。
vanilla-extract 和 Lightning CSS 的特殊处理
在构建时工具链里,fallbackVar()(vanilla-extract)或 Lightning CSS 的 TokenList 解析器,会把 fallbackVar(colorVar, 'blue') 编译成 var(--colorVar__qzfheg0, blue)。这意味着你在 JS 层写的回退逻辑,最终仍落地为标准 var() 语法,和手写效果一致——但要注意,这些工具不改变“空字符串不触发回退”这一底层行为,该踩的坑一个不少。
最常被忽略的点:回退值里不能写 calc(),但你可以把计算结果提前存进另一个变量,再在 fallback 里引用它,比如 var(--h1-size, var(--h1-size-fallback)),其中 --h1-size-fallback 已经是 calc(var(--base-font-size) * 2) 的结果。


















