var()的第二个参数是回退值,仅在变量完全未声明或显式设为unset时生效;空字符串、initial、非法值等均不触发回退,且回退值中可嵌套var()实现多级降级但禁止循环引用。

var() 的第二个参数只在变量完全未声明或被设为 unset 时生效,不是“默认值”,更不兜底非法值、空字符串或 initial —— 这是绝大多数人踩坑的根源。
为什么 var(--color, red) 有时根本不触发回退?
它只对两种情况起作用:变量压根没在任何作用域中声明;或被显式设为 unset(比如 :root { --color: unset; })。其余所有“看似无效”的情况,浏览器都会尝试解析并应用,从而跳过回退:
-
--color: ""(空字符串)→var(--color, red)返回空,样式失效 -
--color: initial→ 按 CSS 继承规则计算,不进回退 -
--color: bluue(拼错)→ 解析失败,此时才触发red -
--color: 123(类型错)→ 同样解析失败,回退生效
验证方式:打开 DevTools → Computed 面板看最终计算值;或执行 getComputedStyle(el).getPropertyValue('--color') —— 返回 "" 表示已声明但为空,返回 null 才是真未定义。
多级回退必须写成合法 CSS 值,不能直接传变量名
想从 --primary 降级到 --base 再到 #000,必须写成:
立即学习“前端免费学习笔记(深入)”;
color: var(--primary, var(--base, #000));
而不是:
color: var(--primary, --base); // ❌ 整条声明被浏览器忽略
原因:var() 第二个参数必须是**可求值的 CSS 值**,--base 只是一个属性名,不是值。嵌套 var() 是允许的,但要注意:
- 嵌套深度无硬性限制,但超过两层(如
var(--a, var(--b, var(--c, #000))))会让调试变困难 - 不能循环引用(如
--a: var(--b, red); --b: var(--a, blue)),会报 CSS parse error - 每个
var()独立查找作用域 ——var(--b, #000)中的--b是在当前元素作用域查,不是向上找:root
IE11 等旧浏览器根本不会解析 var(),必须手动 fallback
var(--bg) 在 IE11 中不是降级,而是整条 CSS 声明被静默丢弃。所以不能只依赖 var() 自带的第二个参数 —— 它对 IE11 完全无效。
正确写法是“静态值 + var() 覆盖”组合,且顺序不能错:
background-color: #fff;<br>background-color: var(--card-bg, #fff);
关键点:
- 两行必须在同一选择器块内
- 简写属性(如
background、border、font)必须拆解为原子属性,每条都加 fallback - 所有变量定义必须放在
:root,否则旧浏览器无法感知 - fallback 值必须带单位(如
12px,不能只写12)
SCSS 编译时无法自动注入运行时回退
SCSS 不解析 var(),也不帮你补 fallback。你写的 color: var(--text) 就原样输出,浏览器 runtime 才决定是否回退。所谓“优雅处理”,靠的是结构设计:
- 用 SCSS 变量提供编译时基础值:
$fallback-text: #333; - 再显式插值:
color: var(--text, #{$fallback-text}); - 真正可配置的接口,必须由 CSS 自定义属性暴露,Sass 只负责组织和兜底
最易被忽略的一点:服务端渲染(SSR)场景下,JS 尚未执行,:root 必须提前注入全部变量 —— 漏一个,就是真未定义,回退才会生效。而一旦漏注却写了空值(如 --size: ""),反而导致降级失效。


















