为什么排版引擎解析 CSS 选择器时一定要从右往左解析?

首先我们要看一下选择器的「解析」是在何时进行的。

主要参考这篇「 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。

因为所有样式规则可能数量很大,而且绝大多数不会匹配到当前的 DOM 元素(因为数量很大所以一般会建立规则索引树),所以有一个快速的方法来判断「这个 selector 不匹配当前元素」就是极其重要的。

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

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

但因为匹配的情况远远低于不匹配的情况,所以逆向匹配带来的优势是巨大的。同时我们也能够看出,在选择器结尾加上「*」就大大降低了这种优势,这也就是很多优化原则提到的尽量避免在选择器末尾添加通配符的原因。

时间: 2024-10-17 17:31:12

为什么排版引擎解析 CSS 选择器时一定要从右往左解析?的相关文章

30个最常用css选择器解析(转自大范甘迪)

你也许已经掌握了id.class.后台选择器这些基本的css选择器.但这远远不是css的全部.下面向大家系统的解析css中30个最常用的选择器,包括我们最头痛的浏览器兼容性问题.掌握了它们,才能真正领略css的巨大灵活性. 1. * * { margin: 0; padding: 0; } 星状选择符会在页面上的每一个元素上起作用.web设计者经常用它将页面中所有元素的margin和padding设置为0. *选择符也可以在子选择器中使用. #container * { border: 1px

你须知道的30个CSS选择器 »

你也许已经掌握了id.class.后台选择器这些基本的css选择器.但这远远不是css的全部.下面向大家系统的解析css中30个最常用的选择器,包括我们最头痛的浏览器兼容性问题.掌握了它们,才能真正领略css的巨大灵活性. 1. * 1 * {margin: 0; padding: 0;} 星状选择符会在页面上的每一个元素上起作用.web设计者经常用它将页面中所有元素的margin和padding设置为0. *选择符也可以在子选择器中使用. 1 #container * { border: 1p

CSS选择器的优化

前面花了几个篇幅着重介绍了CSS的选择器的使用,我将其分成三个部分:CSS3基本选择器.CSS3属性选择器详解以及CSS3伪类选择器详解.那么今天我主要想和大家一起来学习——CSS选择器方面的性能优化.因为对性能这一块一直都是很弱的,所以今天先从选择器开始入手,加强自己.如果你也感兴趣那就跟我一起来吧. 浏览器如何识别你的选择器 首先我们需要清楚,浏览器是如何读取选择器,以识别样式,并将相应的样式附于对应的HTML元素,达到美化页面的效果.Chris Coyier曾在<Efficiently R

CSS选择器优先级总结

CSS三大特性-- 继承. 优先级和层叠. 继承:即子类元素继承父类的样式; 优先级:是指不同类别样式的权重比较; 层叠:是说当数量相同时,通过层叠(后者覆盖前者)的样式. css选择符分类 首先来看一下css选择符(css选择器)有哪些? 1.标签选择器(如:body,div,p,ul,li) 2.类选择器(如:class="head",class="head_logo") 3.ID选择器(如:id="name",id="name_t

CSS系列:CSS选择器

选择器(selector)是CSS中很重要的概念,所有HTML语言中的标记样式都是通过不同的CSS选择器来控制的.用户只需要通过选择对不同的HTML标签进行选择,并赋予各种样式声明,即可实现各种效果. CSS选择器包括:标记选择器.类别选择器.ID选择器及复合选择器. 1. 标记选择器 一个HTML页面由很多不同的标记组成,CSS标记选择器用来声明哪些标记采用哪种CSS样式.因此,每一种HTML标记的名称都可以作为相应的标记选择器的名称. 示例: <style type="text/css

python中pyquery库的css选择器实战解析

1.pyquery部分选择器解释 """pyquery的CSS选择器方法""" from pyquery import PyQuery html = """ <div id="container"> <table class="tablelist" cellpadding="0" cellspacing="0">

导航栏布局时遇到的问题以及解决办法 css选择器优先级

得到的导航栏效果 添加#menu ul li{width:30px;} 效果如图 将会使列表项和分隔区域的宽度同时改变因为id选择器的优先级高于类选择器,此时应该为列表项添加内联样式如图 才能得到如下效果 或者可以使用第二种方法 #menu ul li{ float:left; margin-left:10px;text-align:center;padding-left:10px;实现列表项文字的居中 line-height:28px; height:28px; width:40px; bor

前端开发中常用的CSS选择器解析(一)

你也许已经掌握了id.class.后台选择器这些基本的css选择器.但这远远不是css的全部.下面向大家系统的介绍css中最常用的选择器,包括我们最头痛的浏览器兼容性问题.掌握了它们,才能真正领略css的巨大灵活性. 1.* * { margin: 0; padding: 0; } 星状选择符会在页面上的每一个元素上起作用.web设计者经常用它将页面中所有元素的margin和padding设置为0. *选择符也可以在子选择器中使用. #container * { border: 1px soli

Rendering Engine 主流的浏览器内核(排版引擎、渲染引擎、解释引擎)有哪几种,分别的特点

一.A web browser engine A rendering engine is software that draws text and images on the screen. The engine draws structured text from a document (often HTML), and formats it properly based on the given style declarations (often given in CSS). Example