必须用 :root 声明全局 css 变量,因其语义正确、跨文档兼容、层叠优先且继承链顶端;写 html 或 body 会导致作用域残缺、覆盖风险或静默失效,且变量名须以 -- 开头、每行末尾加分号、冒号无空格、字符串加引号。

必须用 :root 声明,不能写成 html 或 body;变量名以 -- 开头,每个声明末尾必须加分号,否则后续所有变量都会静默失效。
为什么非得用 :root,而不是 html 或 body
表面上 html { --color: red; } 和 :root { --color: red; } 都能读到,但实际有三个关键差异:
-
:root是 CSS 规范定义的“文档根元素”锚点,在 SVG、XML 等非 HTML 文档中仍有效,html会直接失效 - 层叠顺序上,
:root比html更靠前——当两者同时定义同名变量时,:root的值胜出,尤其在 JS 动态注入 style 或 SSR 场景下更稳定 -
body { --x: red; }声明后,html自身、head里的@import样式、甚至同级伪元素都读不到这个变量,因为继承链没挂到顶端
:root 块内声明变量的硬性语法要求
不是“写了就能用”,很多失效是语法细节没守牢:
- 每个声明必须以分号结尾,包括最后一个:
--spacing-sm: 8px;✅,--spacing-sm: 8px❌(会导致后续整块声明被忽略) - 冒号前后不能有空格:
--color: #000✅,--color : #000❌ - 字符串值必须加引号:
--font-family: "Inter", sans-serif;✅,--font-family: Inter, sans-serif;❌(空格会被截断,只剩Inter) - 不能拆单位:
--size: 16;和--unit: px;无法组合使用,font-size: var(--size) var(--unit);是非法语法
如何安全引用 :root 变量(var() 的坑)
var() 不是取值函数,而是带 fallback 的回退机制。不写 fallback 就等于裸奔:
- 必须提供 fallback:
color: var(--text-color, #333);,否则变量未定义时可能继承transparent或初始黑,文字突然消失 - fallback 必须是当前属性的合法值:
font-size: var(--size, 1rem);✅,font-size: var(--size, auto);❌(auto不是font-size的合法值) - 拼错变量名不会报错,只会静默回退:
var(--primry-color)(少个a)→ 直接用 fallback 或初始值,控制台零提示 - 不支持嵌套
var():var(--color, var(--fallback))会整个失效,最多只允许一层 fallback
动态更新 :root 变量的唯一正确方式
CSS 文件里改了 :root 值,页面不会自动响应——所有运行时更新都必须走 JS:
- 正确方式:
document.documentElement.style.setProperty('--primary-color', '#ff5733'); - 错误方式:
document.documentElement.style.cssText = '--primary-color: #ff5733';→ 会清空所有已有自定义属性 - 批量修改建议封装函数,避免重复写
document.documentElement.style - 切换主题时,用
setAttribute('data-theme', 'dark')而非className = 'theme-dark',防止意外覆盖其他 class(如 SSR 注入的 class)
最常被忽略的点:变量是否生效,90% 不是浏览器兼容问题,而是声明位置错了、分号漏了、拼写大小写不一致,或者 fallback 写了个非法值——这些都不会报错,只会在页面上静默失效,调试时极难定位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











