🌳 什么是 Rule Tree?
Rule Tree 是浏览器在构建 CSSOM 时的一部分结构,它组织了 CSS 中的所有规则(Rule),即每一个选择器+声明组合的结构体。
它的作用是:把从不同来源(内部、外部、继承)来的规则,按“层叠规则(Cascading Rules)”归并起来,为后续匹配和计算样式做准备。
🧩 Rule Tree 的结构本质(简化版)
每个 Rule 节点代表一条规则:
1 | { |
🔁 Rule Tree 是怎么“合并规则”的?
假设我们有如下三条规则:
1 | /* 默认浏览器样式 */ |
浏览器处理的顺序:
来源 | 优先级高低 | 说明 |
---|---|---|
浏览器默认(user agent) | 最低 | 最后被覆盖 |
作者样式表(外部CSS) | 中等 | 一般使用的样式 |
行内样式 | 高 | style="" 写的样式 |
!important |
最高 | 无视一般优先级 |
按选择器 + 来源 + specificity + 是否 important 区分不同规则 , 浏览器会将匹配到的多条规则收集到一个集合,然后根据这些因素合并:
多个 CSS 规则可能匹配同一个元素时,浏览器必须选出“赢家”,这个过程称为层叠(cascading)。
💡 合并规则优先级判断标准:
!important
有无- 来源(user / author / user-agent)
- specificity(选择器的具体程度)
- 声明的先后顺序
📚 举个合并例子
1 | /* style1.css */ |
最终谁胜出?
color: blue
(内联) specificity 高- 但
color: green !important
是重要声明
✅ 最终显示颜色为绿色(因为 !important
胜出)。
🔍 浏览器内部:如何构造 Rule Tree?
浏览器内部通常会用如下数据结构:
1 | CSSRule |
Rule Tree 并不是对 DOM 树的映射,而是对选择器规则集合的映射,它将这些规则组合、排序、归类以便查找和比较。
🛠️ 现代浏览器优化:Rule Tree + Style Sharing
像 Firefox 的 Gecko 和 Chrome 的 Blink 引擎,会:
- 使用“Rule Tree”缓存共享规则,避免重复样式计算
- 使用“Computed Style”缓存结果,优化性能
✅ 总结:Rule Tree 如何区分和合并规则?
步骤 | 说明 |
---|---|
区分 | 按选择器 + 来源 + specificity + 是否 important 区分不同规则 |
合并 | 把所有匹配同一元素的规则,按层叠规则合并 |
输出 | 得出一个元素的最终“计算样式”(Computed Style) |
具体拆解你提到的这四个关键维度:选择器 + 来源 + specificity + 是否 !important
是如何让浏览器区分并决定“哪条 CSS 规则最终生效”的。
🧠 背景:多个 CSS 规则可能匹配同一个元素时,浏览器必须选出“赢家”,这个过程称为层叠(cascading)。
✅ 四大决策因子详解
① 选择器(Selector)
哪个选择器能匹配当前元素?可能匹配上多个,例如:
1 | div { color: red; } |
这些都会匹配 <div id="main">
,但最终只能取其中一个。
② 来源(Origin)
CSS 有三种来源,优先级不同:
来源 | 权重(从低到高) |
---|---|
User agent(浏览器默认) | 最低 |
用户样式(用户设置) | 中(通常可被覆盖) |
作者样式(网站写的) | 高(一般我们写的 CSS) |
!important 版本 |
会覆盖上面所有 |
例如:
1 | /* 浏览器默认 */ |
③ Specificity(选择器优先级)
浏览器给选择器打“分”,越具体,分越高,越容易胜出:
选择器类型 | 分值表示形式(a,b,c,d) | 举例 | 说明 |
---|---|---|---|
!important |
特殊处理,最高 | 特例,详见下一项 | |
行内样式(style) | 1,0,0,0 | style="..." |
优先级高于任何选择器 |
ID 选择器(#id) | 0,1,0,0 | #header |
高优先级 |
类、属性、伪类选择器 | 0,0,1,0 | .box , [type=] |
常见 |
元素、伪元素选择器 | 0,0,0,1 | div , p , ::after |
优先级最低 |
示例:
1 | /* specificity: (0,0,0,1) */ |
优先级从高到低:#main
> .text
> p
④ 是否有 !important
这相当于“加特权”:
1 | .box { |
即使 .box
的 specificity 低于其他规则,它也会胜出。
但是:多个 !important
要比 specificity!
1 | .box { |
✅ #main
的规则胜出,因为 !important
且 specificity 更高。
🎯 决策流程图(简化文字版)
1 | 是否有 !important? |
🧪 实战举例分析
HTML:
1 | <div id="main" class="box" style="color: orange;">Hello</div> |
CSS:
1 | /* specificity: 0,0,1,0 */ |
→ 谁胜出?
最终颜色是:橙色(来自 inline style
)
加一条:
1 | .box { |
→ 此时颜色是:紫色(因为 !important
胜出,即使 specificity 低)
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏