:root 通过 --xxx 声明全局css变量,挂载于html根节点,全文档可用;支持任意值类型与calc(),区分大小写;var(--x, fallback)中fallback仅在变量未定义或无效时生效,不可嵌套var();js可动态读写,但ie不支持。

怎么用 :root 定义 CSS 全局变量
直接在 :root 里用 --xxx 命名声明自定义属性,它就自动成为整个文档可用的全局变量。本质是把变量挂载到 document 的根节点(即 html 元素),所有后代都能通过 var(--xxx) 访问。
常见错误是写成 html:root 或 body:root——:root 就是伪类,不需要前置标签名;也有人误以为它只在 CSS 文件顶层生效,其实只要在样式表中被解析到的位置,就会注册变量(但遵循 CSS 级联顺序)。
-
:root的优先级等同于html选择器,比普通类名高,但低于!important或内联 style - 变量名区分大小写:
--Color和--color是两个不同变量 - 支持任意值类型:颜色、尺寸、字符串、甚至
calc()表达式,比如--gap: calc(1rem + 2px) - 不能在
@keyframes或@media内部直接声明:root,但可以在其中使用已定义的变量
var() 取值时 fallback 怎么写才不踩坑
fallback 不是“备选值”,而是“当变量未定义或无效时的降级值”。很多人写成 var(--color, #000) 就以为稳了,结果变量拼错、作用域外访问、或值本身语法错误(比如 --size: 12 缺单位),都会触发 fallback——但你未必意识到问题出在变量本身。
- fallback 只能是单个值或用逗号分隔的多个值(如
var(--shadow, 0 2px 4px rgba(0,0,0,.2), inset 0 1px 0 #fff)),不能是另一个var() - 如果 fallback 里含函数(如
var(--size, calc(1em * 1.2))),该函数仍会执行,但不会再次查变量 - 不要依赖 fallback 掩盖拼写错误:建议开发期配合
CSS.supports('color', 'var(--xxx)')或 DevTools 的“Computed”面板检查变量是否生效
为什么改了 :root 变量,页面没重绘
变量值变了,但使用它的属性(比如 color: var(--text-color))没触发重排重绘,通常是因为浏览器认为样式没变——尤其是变量值语义相同但字符串不同(如 --c: #f00 → --c: red),或变量被用于非动画属性且无 layout effect。
立即学习“前端免费学习笔记(深入)”;
- 修改
:root中变量后,必须确保对应属性实际参与渲染计算,例如改--bg但元素background没用它,自然没反应 - 动态改变量推荐用 JS:
document.documentElement.style.setProperty('--primary', '#007bff'),避免手动替换整个 style 标签 - 部分旧版 Safari 对
var()在transform或filter中的响应有延迟,可加will-change: transform强制图层提升 - 变量不能用于
@media查询条件(如@media (min-width: var(--breakpoint))),这是语法错误
和 CSS 预处理器变量(如 Sass $color)根本区别在哪
预处理器变量在构建时展开为静态值,而 :root + var() 是运行时解析的真变量,支持 JS 动态读写、媒体查询响应、主题切换——但也因此无法做数学运算(var(--a) + var(--b) 不合法),也不能用于选择器或 @import 路径。
- Sass 变量能参与
$a + $b运算,CSS 自定义属性不行;想算就得用calc(var(--a) + var(--b)),且要求两边单位一致或都无单位 - 预处理器变量无法被 JS 获取,
:root变量可通过getComputedStyle(document.documentElement).getPropertyValue('--color')读取 - 兼容性上,IE 完全不支持
:root自定义属性,如需支持得用 PostCSS 插件降级,但会丢失动态能力 - 过度嵌套
var()(比如var(--a, var(--b, black)))虽合法,但可读性和调试成本陡增,简单场景别这么写
真正难的是变量命名的收敛和层级控制——没人管的时候,--header-bg-hover 和 --hover-header-bg 很快就会同时出现,后面谁都不敢删。










