这一步骤中,把和 DOM 节点匹配的所有规则添加到一个列表。 因为可能匹配到多个规则,所以同一属性就可能出现多个声明。 另外,浏览器自身也添加了默认 CSS 规则(用户代理样式表)。 CSS 引擎如何知道应该选择哪个值呢?
这里就有优先级规则出现了。 CSS 引擎创建一个表格。 然后根据不同列对声明做排序。 具有最高优先级的规则胜出。 根据这个表格,CSS 引擎填充已经可以确定的值。 其余的值,则使用层叠。
层叠使 CSS 易于编写和维护。 使用层叠,可以在 body 上设置 color 属性,p 和 span 和 li 中的文本都会使用该颜色(除非有一个更高优先级的覆盖)。
CSS 引擎在表格里查看空白盒子。 如果该属性默认继承,那么 CSS 引擎就沿着树形结构向上,查看祖先节点是否有值。 如果全部祖先节点都没有值,或者该属性不继承,就获得一个默认值。 这时已经为这个 DOM 节点计算了所有样式。
上面看到的表格可能有一点儿误导性。 CSS 有成百上千的属性。 如果 CSS 引擎保持每个 DOM 节点的每个属性值,会很快耗尽内存。
因此,引擎会做 样式结构体共享。 经常在一起的数据(如字体属性)被保存在一个叫做样式结构体的对象里。 不再将全部属性保存在同一对象里,而是让对象只持有指针,指向计算出的样式。 对于每个类别,都有一个指针指向样式结构体,具有此 DOM 节点应有的正确值。 这样节省了内存和时间。 具有相似属性的节点(如兄弟节点)可以把共享的属性指向相同的结构体。 因为很多属性是继承的,如果该后代没有特别指定覆盖的话,祖先节点也可以与后代共享结构体。
这是没有优化时,样式计算的样子。 这里发生了很多工作。 不仅第一次页面加载时发生。 当用户与页面交互、鼠标在元素上悬停、或更改 DOM 时,会反复发生,触发样式重建。 这表明 CSS 样式计算是很好的优化之选…… 过去 20 年里浏览器们一直在测试不同的优化策略。 Quantum CSS 所做的是从不同浏览器引擎中择取最好的策略,并把它们结合起来创造出一个超级快的新引擎。