必须用:root声明CSS全局变量,因其是唯一被规范定义的文档根作用域锚点,确保变量在SVG、Shadow DOM、表单控件及旧版Safari中稳定生效;html或body声明属误用,特异性低、跨上下文失效且不被部分浏览器可靠解析。

必须用 :root,不能用 html 或 body —— 否则变量在 SVG、Shadow DOM、表单控件或旧版 Safari 中大概率失效。
为什么:root是唯一安全位置
它不是“可选项”,而是 CSS 自定义属性作用域的硬性起点:变量靠继承传播,而只有 :root 能确保从 开始向下完整注入。写成 html { --color: red; } 看似能用,实则是误用——它只是普通选择器,特异性低(0-0-1),在 :root[data-theme] 或 @media 规则中会被覆盖;更关键的是,在 SVG 文档或 Web Component 的 Shadow Root 内,html 根本不匹配,而 :root 仍有效。
-
:root特异性为 0-1-0,高于html,避免被业务 class 意外覆盖 - IE11+、Safari 9.1+、Chrome 49+ 全支持,无需 polyfill
- 旧版 Safari(iOS 12.2 之前)对
html声明的变量解析不稳定,:root才可靠
:root块里怎么写才不被浏览器忽略
浏览器对语法极其敏感,错一个字符就等于没声明。常见静默失效原因不是逻辑错,而是书写违规:
- 变量名必须以
--开头:--primary-color✅,primary-color或$primary❌ - 值必须是合法 CSS 值:
--size: 16px✅,--size: 16❌(单位不可省);--font: "Inter", sans-serif✅,--font: Inter, sans-serif❌(无引号的多词字体名会断开) - 避免嵌套引用:
--text: var(--primary)在旧 Safari 中可能直接跳过整条声明 - 声明块必须前置:
:root规则要放在所有用到var(--x)的样式之前,CSS 是顺序解析的
如何让var(--x)真正生效,而不是“看不见”
var() 不报错也不警告,但变量未定义时属性会丢弃(不是继承,不是 fallback 到父级,而是回退到该属性的 initial 值),导致文字透明、背景消失等静默故障。
立即学习“前端免费学习笔记(深入)”;
- 每个
var()必须带 fallback:color: var(--text-primary, #333),第二个参数只在变量未声明或拼写错误时启用 - 不要依赖 fallback 实现主题切换——它只是兜底,不是分支逻辑
- 伪元素和 SVG 必须显式使用:
::before { content: ""; background: var(--bg-primary); },否则不响应变量变更 - 检查是否被
all: unset或inherit中断继承链,这类重置会切断:root变量传递
JS 动态修改时最容易踩的三个坑
调用 document.documentElement.style.setProperty() 看似简单,但实际有隐藏限制:
- 读取值时带空格:
getComputedStyle(document.documentElement).getPropertyValue('--primary')返回" #007bff ",记得.trim() - 不能在内联 style 上声明新变量——
element.style.setProperty('--new', 'val')无效,只支持已存在于:root或该元素上的变量 - 大量逐个 setProperty 会卡 UI 线程;真正轻量的做法是只操作
dataset.theme或 class,让 CSS 规则自动重算整组变量
最易被忽略的一点:变量名大小写敏感,--PrimaryColor 和 --primarycolor 是两个变量,拼错一个字母,var() 就静默 fallback。


















