浏览器底层解析CSS选择器的过程

1.过程

浏览器解析 CSS 选择器的过程大致可以分为以下几个步骤:

1.1 DOM 树构建

浏览器首先会解析 HTML 文档,构建 DOM 树(Document Object Model)。DOM 树表示了 HTML 文档的结构,每个 HTML 元素都是树上的一个节点。

1.2 CSS 解析

浏览器解析 CSS 样式表,将CSS 规则转换成浏览器可以理解的数据结构。这包括解析选择器、属性和值。

1.3 构建选择器列表

浏览器会将 CSS 规则中的选择器部分提取出来,形成一个选择器列表。每个选择器都会被解析成一个更易于匹配的数据结构,例如包含标签名、类名、ID 等信息。

1.4 从右到左匹配

这是 CSS 选择器匹配的关键步骤,也是性能优化的重点。 浏览器从选择器的最右边部分开始,向左逐步匹配。例如,对于选择器div.container p span,浏览器会先查找所有 span 元素,然后向上查找其父元素是否为p,再向上查找是否为.container类名的div元素。这种从右到左的匹配方式可以有效减少需要遍历的元素数量,提高匹配效率。

从右到左匹配的原因:
如果从左到右匹配,例如div.container p span,浏览器需要先找到所有的div元素,然后筛选出带有 .container类的div,再查找其后代元素中所有的p,最后再查找p的后代元素中的span。这需要遍历大量的元素,效率低下。而从右到左匹配则可以避免这种大量的无效遍历。

1.5 生成样式上下文

当一个选择器匹配成功后,浏览器会为匹配的元素生成一个样式上下文。样式上下文包含了所有适用于该元素的样式规则及其对应的值。

1.6 应用样式

最后,浏览器根据生成的样式上下文,将样式应用到对应的 HTML 元素上,最终呈现出页面效果。

2.示例

在生成渲染树的过程中,渲染引擎会根据选择器提供的信息来遍历 DOM 树,找到对应的 DOM 节点后将样式规则附加到上面。来看一段样式选择器代码,以及一段要应用样式的 HTML:
CSS:

.box div span {
  font-size: 20px;
}

HTML:

<div class="box">
  <header>
    <h3>
      <span>这是一个标题</span>
    </h3>
  </header>

  <div>
    <ul>
      <li><a href="http://">内容一</a></li>
      <li><a href="http://">内容二</a></li>
      <li><a href="http://">内容三</a></li>
    </ul>
  </div>
</div>

渲染引擎是怎么根据上述样式选择器去遍历这个 DOM 树的呢?是按照从左往右的选择器顺序去匹配,还是从右往左呢?

为了更直观的查看,我们先将这棵 DOM 树先绘制成图:
在这里插入图片描述
然后我们来对比一下两种顺序的匹配:

从左往右:.box => h3 => span

  • 遍历所有的元素, 找有 .box 类的节点
  • 从 .box 开始遍历所有的⼦孙节点 header、div 、 h3、 ul …
    遍历所有的后代元素后, 知道了, 整个子孙后代只有一个 h3
  • 找到 h3 , 还要继续重新遍历 h3 的所有子孙节点, 去找 span

问题: 会进行大量树形结构子孙节点的遍历, 这是非常消耗成本的 ! 这在真实页面中⼀棵 DOM 树的节点成百上千的情况下,这种遍历方式的效率会非常的低,根本不适合采用。

从右往左:span => h3 => .mod-nav

  • 先找到所有的 span 节点 ,然后基于每⼀个 span 再向上查找 h3
  • 由 h3 再向上查找 .mod-nav 的节点
  • 最后触及根元素 html 结束该分⽀遍历

从右向左的匹配规则, 只有第一次会遍历所有元素找节点, 而剩下的就是在看父辈祖辈是否满足选择器的条件, 匹配效率大大提升!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值