:root 是 css 中匹配文档根元素的伪类,在 html 中等价于 html 元素,但语义更明确、优先级更高,是声明 css 自定义属性的推荐位置;它作为继承链起点确保变量全局可用,且支持嵌套引用(禁止循环)。

什么是:root,它和html有什么区别
:root 是 CSS 中匹配文档根元素的伪类,在 HTML 中它等价于 html 元素,但语义上更明确:它是整个 CSS 作用域的“顶层上下文”,也是 CSS 自定义属性(即常说的“CSS 变量”)最推荐的声明位置。关键在于,:root 的优先级略高于 html——当两者都定义同名自定义属性时,:root 的声明会胜出。
常见错误是直接在 body 或某个 class 下定义 --color-primary,结果发现子元素拿不到,或者被意外覆盖。根本原因:自定义属性遵循继承规则,而 :root 是继承链起点,确保变量从最顶层注入。
怎么声明和使用 CSS 自定义属性
声明必须用双破折号开头,例如 --spacing-sm;使用必须配合 var() 函数,不能直接写值。
-
:root块内声明::root { --color-primary: #007bff; --spacing-md: 1rem; --border-radius: 4px; } - 在其他选择器中使用:
.btn { background-color: var(--color-primary); padding: var(--spacing-md); border-radius: var(--border-radius); } - 支持 fallback 值:
var(--color-primary, #6c757d),当变量未定义时回退到第二个参数 - 不支持在
@media外直接用 JS 动态读取未声明的变量——必须先在:root或某元素上定义,哪怕初始值为空
为什么var(--x)有时不生效或报错
浏览器不会报语法错误,但计算值可能变成 initial 或继承值,表面看就是“没变”。典型场景:
- 拼写不一致:
--text-color和var(--text-colour)不匹配 - 作用域错误:在
:root外声明变量(如写在.theme-dark里),又在:root下用var()引用——此时变量根本不可见 - 类型混用:把带单位的值(如
--size: 16px)和无单位数(如--z-index: 10)混着参与 calc,但calc(var(--size) * 2)是合法的,calc(var(--z-index) + 1)也合法;真正失效的是calc(var(--size) + 1)——单位和数字不能直接相加 - 动态更新后未触发重绘:JS 修改
document.documentElement.style.setProperty('--color', 'red')是即时生效的,但如果目标元素用了will-change: transform等优化,偶尔会卡住,可强制element.style.color = 'transparent'再设回原值来触发
能不能在:root里用var()做嵌套引用
可以,但有严格限制:只能在声明值中用 var(),且不能循环引用。比如:
:root {
--color-base: #333;
--color-text: var(--color-base);
--color-heading: var(--color-text);
}
这是安全的。但下面这样会失效:
:root {
--a: var(--b);
--b: var(--a); /* 循环,最终 --a 和 --b 都计算为 invalid */
}
另外注意:嵌套时 fallback 仅对最外层 var() 生效,var(--missing, var(--fallback)) 中的 var(--fallback) 不会自动展开,它会被当作字符串字面量处理。
实际项目里,建议把基础色、间距、断点这些稳定值放在 :root,主题色等可能切换的值用 JS 控制 document.documentElement.setAttribute('data-theme', 'dark') 配合属性选择器覆盖,比纯 CSS 嵌套更可控。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











