必须在 :root 中声明才能确保全局可见,因为 :root 是 css 继承链起点,html 优先级低,body 声明对 head、title 等不可见;拼写须完全一致且大小写敏感,var() 无 fallback 时值无效,js 读取前需确保已声明。

必须在 :root 中声明,否则就不是全局变量——哪怕只差一层选择器,作用域就断了。
为什么非得用 :root 而不是 html 或 body
:root 是 CSS 继承链的起点,所有后代元素默认继承它的自定义属性;html 虽然等价,但优先级略低,同名变量会被 :root 覆盖;body 声明的变量对 head 里的 <style></style>、@import 的外部样式、甚至 <title></title> 渲染都不可见。
常见错误现象:.header { --color: red; } 后,在 .footer 里写 color: var(--color) —— 结果是继承值或 initial,不是红色。
-
:root是唯一能保证“全文档可见”的锚点,包括内联样式、伪元素、SVG 样式表 - 不能在媒体查询外的
body、.theme-dark等选择器里定义期望全局生效的变量 - 支持嵌套在
@media或@supports内部声明,仍属全局作用域(只要在:root块里)
--xxx 命名和 var() 引用的硬性规则
拼写必须完全一致,大小写敏感,且 var() 只认已声明的变量名——浏览器不会报错,但计算结果会静默 fallback 到继承值或 initial。
典型失效场景:
-
--text-color和var(--text-colour):少一个u,就拿不到值 -
:root { --size: 16px; },然后写width: calc(var(--size) + 1):单位和纯数字不能直接加,会整个表达式失效 -
var(--missing, #000)中第一个参数未定义,回退生效;但若写成var(--missing)且无 fallback,属性值变成无效,可能触发重排或样式丢失 - 在 JS 中读取前没先声明:例如
getComputedStyle(document.documentElement).getPropertyValue('--color')返回空字符串,必须先确保:root里有对应--color
动态更新时容易忽略的渲染细节
JS 修改 document.documentElement.style.setProperty('--color', 'red') 是即时生效的,但某些 CSS 优化机制会让视觉延迟更新。
- 如果目标元素用了
will-change: transform或contain: layout,可能卡住重绘,可临时设element.style.opacity = .99再设回1触发刷新 - 不要在
:root外层用var()做嵌套引用,比如:root { --a: var(--b); --b: blue; }—— 这种顺序不保证执行先后,--a会 fallback - 嵌套引用只允许在声明值中用
var(),且禁止循环:--x: var(--y); --y: var(--x)会导致整个链失效 - 内联样式里写
style="--color: red"只对该元素生效,无法被其他地方的var(--color)读取
真正麻烦的不是怎么写,而是变量声明位置和引用时机之间那毫秒级的依赖关系——尤其在 SSR 或微前端场景下,:root 声明漏掉、顺序错位、或 JS 提前读取,都会让 var() 变成“看起来写了却没用”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











