一种比较CSS规则特异性的有效算法

时间:2012-10-05 09:33:29

标签: css sorting css-specificity

我想知道在以下场景中有效的算法是什么:

给出一组经过解析的css规则,例如

     p.pStyle{margin-bottom:20px;font-family:Arial;}
     p{font-family:Verdana;}
     p.anotherPStyle{margin-bottom:10px;}

从css样式表中,有几个规则集可能适用于给定元素(比如我文档中的<p class="pStyle anotherPStyle">hello</p>)。

我需要首先确定样式表中的哪些规则适用于给定元素(所以这里是p, pStyle and anotherPStyle),然后创建一个能够按特定方式对适用规则进行排序的比较器(来自最具体的)最一般的)。注意:我已经设计了一个算法,一旦排序就应用规则,因此您无需有效地解决该问题。

我一直在玩弄几个想法,即涉及确定给定规则特定的DOM树中的级别的想法......虽然我不确定这是否是正确的方法?< / p>

浏览器引擎如何有效地执行此操作?我希望用Java复制它,但我对其他许多语言都很满意,所以你能提供的任何代码都非常受欢迎。

由于

1 个答案:

答案 0 :(得分:10)

这是由特异性决定的。在这种情况下,由于它们都是同等特定的,因此文件中最后的声明会获胜。

特异性计算

通过对选择器的不同部分进行排名来计算特异性。

从最具体到最低的排名:

  1. 样式属性 - 如果在样式属性中找到规则,则此等级为1。
  2. ID - 对于在选择器中找到的每个ID,此等级会额外获得1。
  3. 类,伪类,属性选择器 - 对于在选择器中找到的每个类,此等级获得额外的1。
  4. 元素 - 对于在选择器中找到的每个元素,此等级获得额外的1。
  5. rank n > rank n+1,无论每个等级有多少分。

    实施例

    ul#nav li.active a
    

    要点是:

    1. 0 - 不是样式属性。
    2. 找到1 - 1个ID。
    3. 找到1个分类名称。
    4. 发现3 - 3个元素。
    5. 因此,该选择器中的每个属性都具有[0,0,1,1,3]的特异性值(我们将在一分钟内达到额外的零)。该值比任何选择器更具体,只要它可能没有ID,例如。

      比较算法:

      1. 在队伍中从左到右。
      2. 比较两个选择器的排名。
      3. 积分较高的等级,获胜。
      4. 如果排名相同,请继续直接进入下一个(不太具体)排名。
      5. 如果所有排名相同,则CSS文档后面的胜出
      6.   

        更重要的说明:

             
            
        • 通用选择器(*)没有特异性值(0,0,0,0)伪元素(例如:first-line)得到0,0,0,1与其不同   获得0,0,1,0
        • 的伪阶级弟兄   
        • 伪类:not()本身不会增加任何特异性,只会在其括号内添加。
        •   
        • !important指令可应用于单一声明,并将点添加到“0”排名,这比任何内容都更具体。   其他。因此,在上面的示例中,在任何规则上添加!important将为   仅将该规则的特异性值 提升为[1,0,1,1,2]
            在没有!important的情况下立即赢得任何其他规则。
        •   

        额外参考

        有关主题的 this great article


        如何确定哪些样式转到哪个元素

        浏览器执行此操作的方法是从从右到左遍历选择器,并在DOM中过滤元素。

        回到上一个例子:

            ul#nav li.active a
        

        浏览器执行以下操作:

        1. 选择a元素。
        2. 现在检查它是否有一个具有li类的.active元素的祖先(这是通过后代组合器:ancestor descendant)。
        3. 现在检查它是否有一个更高的祖先是ul,其ID为#nav(同样,使用了后代组合子)。
        4. 如果某个元素满足所有这些条件,则将样式应用于它。

          你可以阅读:

            

          选择任何a元素
            一个类为.active的祖先,也是li
            它的祖先ID为#nav,也是ul

          您需要拥有一个功能齐全且完整的DOM树才能成功确定哪个元素具有哪些CSS样式。