为何排版引擎解析 CSS 选择器时必定要从右往左解析?

首先咱们要看一下选择器的「解析」是在什么时候进行的。html

主要参考这篇「 How browsers work」(http://taligarsiel.com/Projects/howbrowserswork1.htm)来看,浏览器渲染的过程以 WebKit 为例大体以下:浏览器

 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。spa

由于全部样式规则可能数量很大,并且绝大多数不会匹配到当前的 DOM 元素(由于数量很大因此通常会创建规则索引树),因此有一个快速的方法来判断「这个 selector 不匹配当前元素」就是极其重要的。htm

若是正向解析,例如「div div p em」,咱们首先就要检查当前元素到 html 的整条路径,找到最上层的 div,再往下找,若是遇到不匹配就必须回到最上层那个 div,往下再去匹配选择器中的第一个 div,回溯若干次才能肯定匹配与否,效率很低。blog

逆向匹配则不一样,若是当前的 DOM 元素是 div,而不是 selector 最后的 em,那只要一步就能排除。只有在匹配时,才会不断向上找父节点进行验证。索引

但由于匹配的状况远远低于不匹配的状况,因此逆向匹配带来的优点是巨大的。同时咱们也可以看出,在选择器结尾加上「*」就大大下降了这种优点,这也就是不少优化原则提到的尽可能避免在选择器末尾添加通配符的缘由。it

相关文章
相关标签/搜索