必须在 :root 中声明所有 CSS 变量,因其是规范唯一全局锚点、特异性高且强制继承;漏声明、错命名、错顺序或无 fallback 均导致静默失效。

必须在 :root 中声明,其他地方写等于白写——变量不会被所有元素(尤其是 、、Shadow DOM 内部)正确继承。
为什么不能用 html 或 body 替代 :root
:root 是 CSS 规范唯一指定的全局锚点,特异性为 (0,1,0),高于 html 的 (0,0,1);更重要的是它强制继承,而 html { --color: red; } 在 SSR、Shadow DOM 或内联 SVG 场景下可能断裂。常见现象包括: 背景色仍是白色、all: unset 组件内 var(--spacing-md) 失效。
不推荐写法:
-
html { --bg: #fff; }—— 语义弱,跨文档(如 SVG)不生效 -
body { --text: #333; }——body不是根元素,变量无法向上或跨控件传播 -
.theme-dark { --bg: #1a1a1a; }—— 类选择器优先级不够,且无法保证表单控件读取到
:root 块里必须一次性声明所有用到的变量
漏定义一个变量,页面首次渲染时就会静默 fallback 到属性默认值(比如 color 变成 inherit,margin 变成 0),控制台毫无提示。这不是“等后续覆盖”,而是“缺了就崩”。
正确做法:
- 默认
:root块中完整列出所有主题变量,哪怕深色模式下值相同也不能省略,例如--shadow-sm、--radius-md - 变量名严格小写、用短横线分隔:
--color-primary✅,--ColorPrimary❌,--font size❌ - 值必须合法:带单位(
--size: 16px),运算用calc()(--size: calc(1rem * 2)),禁用裸表达式(--size: 1rem * 2会失效)
主题切换必须用 data-theme,别碰 style.setProperty()
手动调用 document.documentElement.style.setProperty('--bg', '#121212') 看似直接,但会破坏 @media (prefers-color-scheme: dark) 响应逻辑、卡 UI 线程、导致维护爆炸。真正轻量的做法是只操作属性:
- CSS 中用
:root[data-theme="dark"]覆盖变量,变量名必须完全一致(大小写敏感) - JS 切换时用
document.documentElement.setAttribute('data-theme', 'dark'),不要用className = 'dark'(会清掉其他 class) - 初始化必须早于首屏渲染:在
<script></script>标签内直接读localStorage.getItem('theme')并设置,别等DOMContentLoaded
var() 失效时排查这三点
浏览器不会报错,只会静默 fallback,所以排查要直击根源:
- 拼写或大小写错误:
--spacing-xs声明了,却写了var(--spacing-s)或var(--SpacingXS) - 声明顺序错:CSS 文件中
.card { color: var(--text); }出现在:root块之前 → 渲染时变量未定义 - 没写 fallback:
color: var(--text-primary)应该写成color: var(--text-primary, #333),否则变量未定义时样式直接不可控
最易被忽略的一点:所有变量必须在默认 :root 块中声明,哪怕你 100% 确定用户永远用深色模式——因为首次渲染发生在 JS 执行前,没有 fallback 就没有容错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











