根据计算复杂性选择有效的选择器

时间:2012-06-27 02:42:48

标签: css performance css-selectors

鉴于CSS处理细节,最值得注意的是RTL matchingselector efficiency,如何从渲染引擎性能的角度来编写选择器?

这应涵盖一般方面,包括使用或避免伪类,伪元素和关系选择器。

1 个答案:

答案 0 :(得分:6)

在运行时,HTML文档被解析为包含N元素的DOM树,其平均深度为D。应用的样式表中总共有S个CSS规则。

  1. 元素的样式单独应用意味着 N与整体复杂性之间存在直接关系。值得注意的是,这可以通过浏览器逻辑(例如参考缓存和来自相同元素的回收样式)进行一定程度的抵消。例如,以下列表项将应用相同的CSS属性(假设不应用:nth-child等伪类):

    <ul class="sample">
      <li>one</li>
      <li>two</li>
      <li>three</li>
    </ul>
    
  2. 选择器从右到左匹配单个规则资格 - 即如果最右边的键与特定元素不匹配,则不需要进一步处理选择器并将其丢弃。这意味着最右侧的键应该尽可能少的元素匹配。下面,p描述符将匹配更多元素,包括目标容器的外部段落(当然,这将不适用规则,但仍会导致更多的资格检查迭代)特别选择器):

    .custom-container p {}
    .container .custom-paragraph {}
    
  3. 关系选择器:后代选择器最多需要迭代D元素。例如,如果元素处于父子关系中,成功匹配.container .content可能只需要一步,但是在元素可以之前,需要遍历DOM树到html。确认不匹配,安全丢弃规则。这也适用于链式后代选择器,但有一些限制。

    另一方面,>子选择器,+相邻选择器或:first-child仍然需要额外的元素进行评估,但只有一个隐含的深度,并且永远不会需要进一步的树遍历。

  4. :before:after等伪元素的behavior definition意味着它们不属于RTL范例。假设的逻辑是,在规则指示在元素的内容之前或之后插入它之前,本身没有伪元素(这反过来需要额外的DOM操作,但不需要额外的计算来匹配选择器本身)。

  5. 我找不到有关伪类的任何信息,例如:nth-child():disabled。验证元素状态需要额外的计算,但从规则解析的角度来看,只有从RTL处理中排除它们才有意义。

  6. 鉴于这些关系,主要应通过最小化CSS选择器的深度和解决上述第2点来降低计算复杂度O(N*D*S)。与最小化CSS规则或HTML元素的数量相比,这将导致可量化的更强的改进^

    浅层,最好是单层,特定选择器的处理速度更快。 Google将其提升到一个全新的水平(以编程方式,而非手动!),例如很少有三个键选择器和搜索结果中的大多数规则看起来像

    #gb {}
    #gbz, #gbg {}
    #gbz {}
    #gbg {}
    #gbs {}
    .gbto #gbs {}
    #gbx3, #gbx4 {}
    #gbx3 {}
    #gbx4 {}
    /*...*/
    

    ^ - 从渲染引擎性能的角度来看,这是真的,总会有其他因素,如流量开销和DOM解析等。

    来源:1 2 3 4 5