自定义CSS变量必须在:root中声明且以--开头,因只有:root是所有元素共同祖先,确保继承有效;写在html/body或class中会导致作用域受限或兼容性问题。

必须在 :root 中声明,且变量名以 -- 开头,否则不是全局变量,也不会被 var() 读取。
为什么只能写在 :root 里,不能写在 html 或 body
虽然 html { --color: red } 在多数浏览器中能工作,但语义不明确、特异性不稳定,且 IE 完全不支持;body { --color: red } 声明的变量无法被 自身、 内样式或未包裹的表单控件(如独立 <input>)继承——因为自定义属性靠继承传播,而只有 :root 是所有元素的共同祖先。写在普通 class 如 .theme-dark 里,变量只对该 class 及其后代生效,根本不算“全局”。
:root 块里怎么写才不会静默失效
常见静默失效不是报错,而是颜色/尺寸回退到浏览器默认值,排查困难。关键点:
- 每个用到的变量必须在默认
:root块中完整声明,哪怕深色模式下值相同也不能漏,例如--shadow-sm在暗色主题里也要先在默认块中定义 - 变量名严格区分大小写,
--Primary-Color和--primary-color是两个变量 - 每条声明末尾必须加分号,
--color-bg: #fff缺少分号会导致后续声明全部跳过 - 变量值要带单位(如
16px、0 1px 2px rgba(0,0,0,0.1)),不能只写数字
如何配合 data-theme 实现主题切换
核心是复用同一组变量名,在不同 :root 规则下覆盖值:
立即学习“前端免费学习笔记(深入)”;
:root {
--bg-primary: #ffffff;
--text-primary: #1a1a1a;
--border-color: #e0e0e0;
}
:root[data-theme="dark"] {
--bg-primary: #121212;
--text-primary: #eeeeee;
--border-color: #333333;
}
切换时用 JS 执行:document.documentElement.setAttribute('data-theme', 'dark')。注意别用 className = 'dark' 替换,会清掉其他 class(比如 SSR 标记或 A/B 测试标识)。
var() 使用时最常踩的坑
var() 不是字符串替换,它只在计算属性值时求值,且失败时直接 fallback:
-
color: var(--undefined-var);→ 文字变透明(继承链中断),不是报错 -
color: var(--undefined-var, black);→ 显式 fallback,推荐始终带上第二个参数 -
color: --undefined-var;→ 语法错误,整条声明无效 - 后备值可以嵌套:
color: var(--special-color, var(--default-color, #000));
变量作用域不可跨 Shadow DOM,如果用 Web Components,得在 :host 或 ::slotted 里手动透传,:root 的值不会自动穿透。


















