必须在 :root 中声明 CSS 自定义属性,因其是唯一全局锚点且强制继承;漏声明、缺分号、无单位或大小写错误均导致静默回退至浏览器默认值。

必须写在 :root 里,其他地方声明等于没写——、、Shadow DOM 内部都会 fallback 到浏览器默认值,且控制台不报错。
为什么不能用 html 或 body 替代 :root
:root 是 CSS 规范唯一指定的全局锚点,特异性为 (0,1,0),高于 html 的 (0,0,1);更重要的是它强制继承,而 html { --color: red } 在 SSR、内联 SVG 或 Shadow DOM 场景下可能断裂。常见现象包括: 背景色仍是白色、all: unset 组件内 var(--spacing-md) 失效。
-
html { --bg: #fff }:语义弱,跨文档(如 SVG)不生效 -
body { --text: #333 }:body不是根元素,变量无法向上或跨控件传播 -
.theme-dark { --bg: #1a1a1a }:类选择器优先级不够,且无法保证表单控件读取到
: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 测试标识) - 初始化必须早于首屏渲染:在
<script></script>标签内直接读localStorage.getItem('theme')并设置,别等DOMContentLoaded - 后备值推荐始终带上第二个参数:
color: var(--undefined-var, black);嵌套 fallback 也合法:color: var(--special-color, var(--default-color, #000))
var() 使用时最常踩的坑
var() 不是字符串替换,它只在计算属性值时求值,且失败时直接 fallback:
-
color: var(--undefined-var)→ 文字变透明(继承链中断),不是报错 -
color: var(--undefined-var, black)→ 显式 fallback,推荐始终带上第二个参数 -
color: --undefined-var→ 语法错误,整条声明无效 - 变量作用域不可跨 Shadow DOM,如果用 Web Components,得在
:host或::slotted里手动透传,:root的值不会自动穿透
最容易被忽略的是:漏声明一个变量,页面首次渲染就静默 fallback 到属性默认值(比如 color 变成 inherit,margin 变成 0),控制台毫无提示——这不是“等后续覆盖”,而是“缺了就崩”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











