var()的第二个参数是回退值,仅在变量完全未声明或设为unset时生效;已声明为空字符串、initial、非法值等均不触发回退,多级回退须用var(--a, var(--b, #000))嵌套实现。

var() 的第二个参数不是“默认值”,而是“回退值”
很多人写 color: var(--text-color, #333) 时,下意识觉得“只要 --text-color 不好使,就用 #333”。但实际规则更窄:它只在 --text-color **完全未声明**,或被显式设为 unset 时才启用。一旦变量被声明过,哪怕值是空字符串 --text-color: ""、拼错的颜色 --text-color: bluue、或 initial,浏览器仍会尝试解析该值——此时回退值被跳过,不会生效。
验证方式很简单:getComputedStyle(document.documentElement).getPropertyValue('--text-color') 返回 "" 或 "bluue",就说明变量已存在,回退没机会触发。
多级回退必须靠嵌套 var() 实现
CSS 变量本身不支持“定义时自带默认值”,也没有 var(--a, --b, #000) 这种三参数语法。要实现多级降级,唯一合法方式是把第二个参数写成另一个 var() 调用:
color: var(--text-primary, var(--text-base, #333));
这行代码的执行逻辑是:
立即学习“前端免费学习笔记(深入)”;
- 先查
--text-primary:若未声明或为unset→ 查--text-base - 再查
--text-base:若也未声明或为unset→ 最终用#333 - 任意一级变量只要“已声明”,哪怕值非法(如
--text-base: 123px),其后续回退链就中断
⚠️ 注意:var(--text-primary, --text-base) 是非法写法,整个 CSS 声明会被浏览器忽略。
嵌套回退的常见陷阱
嵌套看似灵活,但几个细节极易出错:
-
var(--a, var(--b, var(--c, #000)))超过两层后,调试成本陡增;Chrome 会静默忽略循环引用(如--a: var(--b); --b: var(--a)),但 Safari 可能报CSS Parser: cycle detected - 回退值中的
var()在当前选择器作用域内查找,不向上穿透到:root或父组件;如果.card里没定义--bg-base,var(--bg-base, #fff)就直接取#fff,不会去:root找 - 回退值里不能用
calc(var(--x))或rgba(var(--r), ...)等组合——部分旧版 Safari 会静默失效,建议拆成独立变量或 JS 补位
空字符串和 JS 动态设置时的特殊处理
这是最常被忽略的一环:JS 设置变量时,el.style.setProperty('--size', '') 会让 var(--size, 16px) 永远返回空字符串,而不是降级到 16px。因为 '' 是一个已声明的有效值(尽管为空)。
安全做法只有两种:
- 设置前做兜底:
el.style.setProperty('--size', size || '16px') - 真要清空并触发回退,用
el.style.setProperty('--size', 'unset')(注意 IE 和部分旧 Android WebView 不支持unset)
别指望浏览器自动感知“这个空值等于没定义”——它只认声明状态,不认业务语义。


















