:root 是定义 css 自定义属性的唯一可靠位置,因其特异性(0-1-0)高于 html(0-0-1),且规范规定其在层叠中更靠前,即使 html 带 !important 也优先覆盖;旧 safari、非 html 文档、shadow dom 等场景下 html 声明会静默失效。

:root 是定义 CSS 自定义属性(--xxx)的唯一可靠位置,html 选择器在部分旧 Safari 和跨文档场景下会失效。
为什么 :root 的优先级比 html 高?
CSS 特异性规则中,:root 是伪类选择器(特异性 0-1-0),html 是类型选择器(特异性 0-0-1)。即使两者都写在同一份样式表里,:root 的声明也会覆盖 html 中同名变量。更关键的是,规范明确要求 :root 在层叠顺序中“更靠前”——哪怕 html 带了 !important,:root 的变量仍能胜出。
哪些场景下 html { --x: y } 会静默失败?
- 旧版 Safari(≤14.1):在
html下声明的自定义属性无法被子元素通过var(--x)继承,而:root没这个问题 - 非 HTML 文档:比如 SVG 或 XHTML,
:root自动匹配<svg></svg>或根节点,html选择器直接不生效 - Shadow DOM 外部变量注入:若在宿主文档用
html定义变量,Web Component 内部无法继承;:root是标准继承链起点,行为更可预期
变量声明位置错误的典型表现
常见错误现象包括:var(--color-primary) 渲染为默认色、控制台无报错、开发者工具里变量显示“invalid”或空值。这往往不是语法错,而是作用域没挂对地方。
- 写成
body { --c: red; }→<style></style>标签、<title></title>等非 body 子节点拿不到该变量 - 写成
.theme-dark { --c: blue; }→ 变量只在该 class 元素及其后代生效,无法全局使用 - 漏写分号:
:root { --size: 16px --color: #000 }→--color声明静默丢弃,后续所有变量都不生效
实际项目中怎么写才最稳?
直接用 :root 块集中声明,别绕弯:
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
:root {
--color-primary: #007bff;
--spacing-md: 1rem;
--border-radius: 4px;
}
主题切换时也基于它扩展:
:root[data-theme="dark"] {
--color-primary: #1e88e5;
--color-bg: #1a1a1a;
}
注意:不要在 :root 里嵌套 @media 直接改变量值,响应式主题应统一由 JS 控制 data-theme 属性,避免和用户手动切换冲突。
真正容易被忽略的点是:变量一旦在 :root 外声明,就不是“全局”的——它只是某个选择器作用域内的局部变量,哪怕你把它写在 html 里,也不等于挂到了继承链顶端。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










