不二如是 发表于 2019-9-12 15:47:43

实用Tips - 55 - 你还不知道CSS选择器从右往左解析?

本帖最后由 不二如是 于 2019-10-8 15:07 编辑

相信很多鱼油在一开始接触 CSS 的时候都会看到一条规则就是尽量少使用层级关系,比如尽量不要写成:

#div P.class {
color: red;
}
而是写成:

.class {
color: red;
}
之所以需要这么写,给的解释是这样可以减少选择器匹配的次数。

初看觉得哦,有点道理啊,但是往细了再想想:

如果我把层级定的足够的清晰分明,那不是可以直接去掉很多不对应的CSS选择器的索引路径的么?为什么都是建议少使用层级关系呢?
原因其实很简单,我们犯了一个经验主义错误:

默认 CSS 选择器是从左往右进行解析的。
实际上恰恰相反,CSS 选择器是:**** Hidden Message *****

这个事实是不是很颠覆一般的认识?

可能这里很多人就要问了,为什么浏览器厂商要搞出这种反人类的解析顺序?

难道 CSS 也跟 JS 一样当初几个浏览器厂商互相之间大打出手怎么让你难受怎么来?

其实之所以要这么做是为了更快的找到对应的样式!

CSS选择器是从右往左解析滴。


CSS选择器进行优化的必要性

OK,具体的情况具体分析,我们先来看一看多次用到的浏览器渲染过程图:



在图中我们可以看到 HTML 解析出了一棵 DOM tree,与此同时样式脚本则解析生成了一个 style rules,也可以说是一个 CSS tree 。

最后,DOM tree 同 style rules 一同结合解析出一颗 Render Tree 。

而 Render Tree 就是包含了一个 dom 对象以及为其计算好的样式规则,提供了布局以及显示方法。

因为不清楚一个 DOM 对象上究竟对应着哪些样式规则,所以只能选择一个最笨的办法,即每一个 DOM 对象都遍历一遍 style rules 。

DOM 对象的数量相信大家也都清楚,如果每次遍历 style rules 都是像一个晒太阳的老大爷一样的悠哉游哉,那么鼠标厂商应该会很开心。

嗯,摔坏了正好买新的嘛~~~因此对 CSS 选择器进行优化就是一个必须的事情了。


从右往左解析到底好在哪里

假如有如下的一段HTML:

<div id="div1">
<div class="a">
<div class="b">
...
</div>
<div class="c">
<div class="d">
...
</div>
<div class="e">
...
</div>
</div>
</div>
<div class="f">
<div class="c">
<div class="d">
...
</div>
</div>
</div>
</div>
和如下的CSS:

#div1 .c .d {}
.f .c .d {}
.a .c .e {}
#div1 .f {}
.c .d{}
假如我们的 CSS 解析器是从左往右进行匹配的,那么会生成如下的 style rules:



首先,#div1 .c .d {} .f .c .d {}.c .d{}这三个选择器里面都含有 .c .d{}这么一个公用样式。

所以哪怕是我们的 DOM 节点明确了是在 #div1 下面都必须对 style rules 进行全部的匹配查找。

这样一来基本上可以说是每一个 DOM 节点都必须完全遍历一遍 style rules,不然搞不好就会漏掉一些公用样式之类的。

所以想着将层级写的更加详细就能去掉很多不对应的 CSS 选择器的索引路径的就不要想了,不管你写的多细,你总是需要把整个 style rules 都遍历一遍。

不然万一漏掉了某个公用样式不就完蛋了。

那么如果我们换成从右向左进行解析就能够避免这种情况了么?

请看下面这个 style rules:



别的先不提,最少这个节点就少了很多啦。

哪怕我这里同样是需要全部遍历一遍就冲着减少了这么多个节点也要从右往左进行解析啊!

更重要的是,只要有公用样式,那么选择器最右边的那个类型选择器一定是相同的,如此公共样式就很自然的都集中到一个分支上。

这个时候我们完全可以将其他不匹配的路径全部去掉而不用担心会漏掉某些个公用样式了。

虽然当这颗CSS树在遍历的时候还有有部分节点会遍历到最后才能确定到底是不是匹配的,但总的来说从右往左进行解析还是会比从左往右解析要少很多次的匹配。

这样带来的效率提升是显而易见的!

同时,这也是不建议使用 * 通配符来进行样式匹配的原因:

浏览器专门建立了一个反常规思维的从右往左的匹配规则就是为了避免对所有元素进行遍历,你直接一个通配符等于之前的工作都白做了。
最后,从右往左进行解析还有一个好处那就是从右往左进行匹配的时候,匹配的全部是 DOM 元素的父节点。

而从左往右进行匹配的时候时候,匹配的全部是 DOM 元素的子节点,这样就避免了 HTML 与 CSS 没有下载完需要进行等待的情形。



http://xxx.fishc.com/forum/201803/20/101934b3igkgm9hgbgz0ck.gif

如果喜欢,别忘了评分{:10_281:} :

http://xxx.fishc.com/forum/201709/19/094516hku92k2g4kefz8ms.gif

这位鱼油,如果喜欢本系列HTML帖子,请订阅 专辑☞(传送门)(不喜欢更要订阅{:10_278:} )

zltzlt 发表于 2019-9-22 21:14:54

我当然知道啦,不用你说哦{:5_109:}

一个账号 发表于 2019-9-28 15:41:47

我当然知道啦,不用你说哦

bangbang-ande 发表于 2019-9-30 12:43:25

我当然知道啦,不用你说哦

七世 发表于 2019-10-23 16:07:13

看看吧

LYF511 发表于 2019-11-19 18:59:45

我当然知道啦,不用你说哦

鱼豆腐爱吃猫 发表于 2019-12-10 20:34:54

谨言清行 发表于 2020-2-25 00:43:08

我当然知道啦,不用你说哦

优时风 发表于 2020-5-12 11:00:49

我当然知道啦,不用你说哦

tjuwlb 发表于 2020-6-6 10:19:29

我当然知道啦,不用你说哦

sHeCanFly 发表于 2020-11-2 09:33:38

我当然知道啦,不用你说哦

隔壁繁星吖 发表于 2021-1-29 21:57:10

我当然知道啦,不用你说哦
页: [1]
查看完整版本: 实用Tips - 55 - 你还不知道CSS选择器从右往左解析?