前段壁咚!浏览器的渲染机制之CSS
- HTML Parser 生成的 DOM 树
- 其二,CSS Parser 生成的 Style Rules
Webkit CSS 解析器
- 通过调用
CSSStyleSheet
的parseString
函数,将上述 CSS 解析过程启动,解析完一遍后,把 Rule 都存储在对应的CSSStyleSheet
对象中 - 目前规则依然是不易于处理的,还需要将之转换成
CSSRuleSet
。也就是将所有的纯样式规则存储在对应的集合当中,这种集合的抽象就是CSSRuleSet
-
CSSRuleSet
提供了一个addRulesFromSheet
方法,能将CSSStyleSheet
中的 rule 转换为CSSRuleSet
中的 rule - 基于这些个
CSSRuleSet
来决定每个页面中的元素的样式
选择器的解析顺序
排版引擎解析 CSS 选择器时是从
右往左
解析
-
HTML
经过解析生成DOM Tree
;而在 CSS 解析完毕后,解析的结果将与 DOM Tree 的内容一起进行分析建立一棵Render Tree
,最终用来进行绘图。Render Tree
中的元素(WebKit 中称为「renderers」,Firefox 下为「frames」)与 DOM 元素相对应,但非一一对应:一个 DOM 元素可能会对应多个
renderer,如文本折行后,不同的「行」会成为 render tree 种不同的 renderer。也有的 DOM 元素被 Render Tree 完全无视,比如display:none
的元素。 - 在建立
Render Tree
时(WebKit 中的「Attachment」过程),浏览器要为每个 DOM Tree 中的元素根据 CSS 的解析结果(Style Rules)来确定生成怎样的 renderer。对于每个 DOM 元素,必须在所有 Style Rules 中找到符合的 selector 并将对应的规则进行合并。选择器的「解析」实际是在这里执行的,在遍历 DOM Tree 时,从 Style Rules 中去寻找对应的 selector。 - 所有样式规则可能数量很大,而且绝大多数不会匹配到当前的 DOM 元素(因为数量很大所以一般会建立规则索引树),所以有一个快速的方法来判断「这个 selector 不匹配当前元素」就是极其重要的。
- 如果正向解析,例如
「div div p em」
,我们首先就要检查当前元素到html
的整条路径,找到最上层的 div,再往下找,如果遇到不匹配就必须回到最上层那个 div,往下再去匹配选择器中的第一个 div,回溯若干次才能确定匹配与否,效率很低。
应用
- id是唯一的,id选择器的权重也是较高的,所以不要写成
p#id1
这个亚子降低解析效率 - 避免
深层次
的子元素选择器 - 慎用
ChildSelector
- 慎用
attribute selector
(Vue的scoped基于此实现的) - 用依赖继承,如果某些属性可以继承