在生成渲染树的过程中,渲染引擎会根据选择器提供的信息来遍历 DOM 树,找到对应的 DOM 节点后将样式规则附加到上面。
来看一段样式选择器代码、以及一段要应用样式的 HTML:
css:
.mod-nav h3 span {font-size: 16px;
}
html:
<div class="mod-nav"><header><h3><span>标题</span></h3></header><div><ul><li><a href="#">项目一</a></li><li><a href="#">项目一</a></li><li><a href="#">项目一</a></li></ul></div>
</div><div class="box">...
</div>
渲染引擎是怎么根据以上样式选择器去遍历这个 DOM 树的呢?是按照从左往右的选择器顺序去匹配,还是从右往左呢?
为了更直观的观查,我们先将这棵 DOM 树先绘制成图:
然后我们来对比一下两种顺序的匹配:
-
遍历所有的元素, 找有 .mod-nav 类的节点
-
从
.mod-nav
开始遍历所有的⼦孙节点header
、div
、h3
、ul
....遍历所有的后代元素后, 知道了, 整个子孙后代只有一个 h3
-
找到
h3
, 还要继续重新遍历h3
的所有子孙节点, 去找span
问题: 会进行大量树形结构子孙节点的遍历, 这是非常消耗成本的!
这在真实页面中⼀棵 DOM 树的节点成百上千的情况下,这种遍历方式的效率会非常的低,根本不适合采用。
从右往左:span => h3 => .mod-nav
-
先找到所有的
span
节点 ,然后基于每⼀个span
再向上查找h3
-
由
h3
再向上查找.mod-nav
的节点 -
最后触及根元素
html
结束该分⽀遍历...
从右向左的匹配规则, 只有第一次会遍历所有元素找节点, 而剩下的就是在看父辈祖辈是否满足选择器的条件, 匹配效率大大提升!
因此,浏览器遵循 “从右往左” 的规则来解析 CSS 选择器!