:root 优先级(0-1-0)高于 html(0-0-1),故同属性下 :root 规则覆盖 html;它支持跨文档类型、动态根节点及全局 CSS 变量,是更健壮的根作用域选择。

:root 和 html 选择器的优先级差异直接影响样式覆盖逻辑
两者都匹配 HTML 文档的根元素,但 :root 的 CSS 优先级是 0-1-0,而 html 是 0-0-1。这意味着当它们定义了相同属性(比如 background-color 或 --primary 自定义属性),:root 规则会胜出。
常见错误现象:在同一个样式表里写了:
:root { --color: #007bff; }
html { --color: #6c757d; }
结果所有用 var(--color) 的地方都取到 #007bff,不是因为 html 没生效,而是它被更高优先级的 :root 覆盖了。
- 这个差异在变量定义场景中尤其关键——自定义属性(CSS 变量)只能在 :root 或元素上声明,而 :root 是最常用、最可靠的全局作用域
- 如果你用
!important强行提升html的声明,虽然能绕过优先级,但破坏可维护性,不推荐 - 检查是否被覆盖,可用浏览器开发者工具的“Computed”面板看最终生效的声明来源
:root 支持跨文档类型,html 仅限 HTML
:root 是语义化的“文档根元素”,在 SVG、XML 或某些 Web Component Shadow DOM 场景中依然有效;而 html 选择器只对 HTML 文档中的 <html> 标签起作用,遇到 <svg> 根节点就完全失灵。
立即学习“前端免费学习笔记(深入)”;
使用场景举例:一个内联 SVG 图标需要复用主站的主题色变量:
<svg viewBox="0 0 24 24">
<style>
:root { --icon-fill: var(--primary, #007bff); }
path { fill: var(--icon-fill); }
</style>
<path d="M12..." />
</svg>
这里用 :root 能让变量在 SVG 文档内部生效;换成 html 就无效,因为 SVG 没有 <html> 元素。
- 如果你的项目要支持多格式输出(如 HTML + SVG + 打印 PDF 的嵌入样式),
:root是更健壮的选择 - 注意:SVG 中的
:root匹配的是<svg>元素本身,不是外层 HTML 的<html>—— 它的作用域是当前文档树
动态替换根元素时,:root 仍保持响应,html 会失效
HTML 规范允许用 JavaScript 替换 documentElement(即 <html>)。一旦执行 document.documentElement.replaceWith(newRoot),原来写死的 html 选择器就彻底不匹配任何元素;而 :root 会自动跟随新根节点。
实操建议:
- 除非你明确知道永远不会动根节点(比如纯静态页面),否则涉及主题切换、微前端沙箱、或 SSR hydration 后重挂载的场景,优先用
:root - IE9+ 全面支持
:root,现代项目基本无需兼容顾虑;若真需支持 IE8,只能退回到html+ 类名 hack - 不要依赖
html做全局变量容器——它不具备语义上的“根作用域”保证
实际项目中该选哪个?看用途再决定
如果只是设个背景色或字体,html 和 :root 效果几乎一样,但习惯上统一用 :root 更安全;一旦涉及 CSS 变量、跨文档、或未来可能的根节点操作,:root 就不是“建议用”,而是“必须用”。
容易被忽略的一点:很多团队把 :root 当成“只是写变量的地方”,却忘了它本身也是个真实选择器——它上面定义的普通样式(比如 font-size、line-height)会直接作用于 <html>,且不可被子元素继承覆盖(除非显式重设)。这点和 html 完全一致,但优先级优势让它更可靠。


















