var()的第二个参数是回退值,仅在变量完全未声明或显式设为unset时生效;已声明为空字符串、initial、inherit或非法值均不触发回退,这是CSS规范行为而非bug。

var() 的第二个参数不是“默认值”,是回退值,只在变量**完全未声明**或被显式设为 unset 时生效;已声明为空字符串 ""、initial、inherit 或非法值(如 bluue)均不触发——这是规范行为,不是 bug。
var() 回退值只对“真未定义”生效
很多人写 :root { --color: ""; },再用 color: var(--color, #000);,结果文字透明。原因:空字符串 "" 是合法值,浏览器会取它,而该值在 color 属性上等价于无效声明,最终降级为 inherit,而非跳到 #000。
- 验证是否“真未定义”:用
getComputedStyle(el).getPropertyValue('--color'),返回""且该变量在任何作用域(:root、父元素、内联 style)都未出现过,才算未定义 -
unset是唯一能显式让变量“变回未定义状态”的值:--color: unset;后,var(--color, #000)才会取#000 - 已声明但值非法(如
--size: 12pxpx;),部分浏览器仍尝试解析,不一定走回退;只有规范明确不接受的值(如color: bluue)才可能触发
多级回退必须嵌套 var(),但有严格限制
想 fallback 到主题色 → 基础色 → 字面量,得靠嵌套:background-color: var(--bg-color, var(--fallback-bg, #fff));。浏览器按顺序查找:先试 --bg-color → 未定义则试 --fallback-bg → 再未定义才用 #fff。
- 嵌套建议不超过两层,最内层必须是字面量(如
#000、1rem),避免间接依赖太多变量增加维护成本 - 禁止循环引用:
var(--a, var(--b, var(--a, black)))或--a: var(--b); --b: var(--a)会导致静默失效,最终渲染为属性初始值(如color: inherit) - 回退值中不能含未闭合的括号或逗号分隔的多值(如
1px solid, red会被截断),但rgba(0,0,0,0.5)没问题
JS 动态设置变量时,空字符串不会触发回退
执行 el.style.setProperty('--size', '') 后,font-size: var(--size, 16px) 依然取空字符串,不会切到 16px。因为 '' 是合法字符串值,不是“未定义”。
立即学习“前端免费学习笔记(深入)”;
- 要让 JS 触发回退,得删掉变量:
el.style.removeProperty('--size'),或设为无效值(如'not-a-length')或'unset' - 服务端渲染(SSR)场景下,JS 还没执行前,CSS 变量全靠 HTML 中的
:root声明撑着;漏写就是真未定义,回退值会立即生效 - 频繁调用
getComputedStyle()读未定义变量会触发重排,滚动中尤其要注意性能
最容易被忽略的是:回退值本身不是终点,而是新一次变量查找的起点;你写的 var(--x, #000) 里那个 #000 看似稳妥,但如果它来自另一层 var(--y, #000),而 --y 又依赖 --x,链就断了——这种隐式循环很难 debug,得靠 DevTools 的 Computed 面板逐级看最终计算值。


















