鱼C论坛

 找回密码
 立即注册
查看: 1413|回复: 11

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

[复制链接]
发表于 2019-9-12 15:47:43 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

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

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

  1. #div P.class {
  2. color: red;
  3. }
复制代码

而是写成:

  1. .class {
  2. color: red;
  3. }
复制代码

之所以需要这么写,给的解释是这样可以减少选择器匹配的次数。

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

如果我把层级定的足够的清晰分明,那不是可以直接去掉很多不对应的CSS选择器的索引路径的么?为什么都是建议少使用层级关系呢?

原因其实很简单,我们犯了一个经验主义错误:

默认 CSS 选择器是从左往右进行解析的。

实际上恰恰相反,CSS 选择器是:
游客,如果您要查看本帖隐藏内容请回复


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

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

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

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

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


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

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

1.jpeg


在图中我们可以看到 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:

  1. <div id="div1">
  2. <div class="a">
  3. <div class="b">
  4. ...
  5. </div>
  6. <div class="c">
  7. <div class="d">
  8. ...
  9. </div>
  10. <div class="e">
  11. ...
  12. </div>
  13. </div>
  14. </div>
  15. <div class="f">
  16. <div class="c">
  17. <div class="d">
  18. ...
  19. </div>
  20. </div>
  21. </div>
  22. </div>
复制代码

和如下的CSS:

  1. #div1 .c .d {}
  2. .f .c .d {}
  3. .a .c .e {}
  4. #div1 .f {}
  5. .c .d{}
复制代码

假如我们的 CSS 解析器是从左往右进行匹配的,那么会生成如下的 style rules:

2.jpeg


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

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

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

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

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

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

请看下面这个 style rules:

3.jpeg


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

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

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

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

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

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

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

浏览器专门建立了一个反常规思维的从右往左的匹配规则就是为了避免对所有元素进行遍历,你直接一个通配符等于之前的工作都白做了。

最后,从右往左进行解析还有一个好处那就是从右往左进行匹配的时候,匹配的全部是 DOM 元素的父节点。

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





                               
登录/注册后可看大图


如果喜欢,别忘了评分


                               
登录/注册后可看大图


这位鱼油,如果喜欢本系列HTML帖子,请订阅 专辑&#9758;传送门)(不喜欢更要订阅

评分

参与人数 1荣誉 +5 鱼币 +5 贡献 +3 收起 理由
睦ちゃん她爹 + 5 + 5 + 3

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-9-22 21:14:54 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-28 15:41:47 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-9-30 12:43:25 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-10-23 16:07:13 | 显示全部楼层
看看吧
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-11-19 18:59:45 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-12-10 20:34:54 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-2-25 00:43:08 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-5-12 11:00:49 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-6 10:19:29 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-11-2 09:33:38 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2021-1-29 21:57:10 | 显示全部楼层
我当然知道啦,不用你说哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-19 04:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表