我想知道在以下场景中有效的算法是什么:
给出一组经过解析的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复制它,但我对其他许多语言都很满意,所以你能提供的任何代码都非常受欢迎。
由于
答案 0 :(得分:10)
这是由特异性决定的。在这种情况下,由于它们都是同等特定的,因此文件中最后的声明会获胜。
通过对选择器的不同部分进行排名来计算特异性。
从最具体到最低的排名:
rank n > rank n+1
,无论每个等级有多少分。
ul#nav li.active a
要点是:
因此,该选择器中的每个属性都具有[0,0,1,1,3]
的特异性值(我们将在一分钟内达到额外的零)。该值比任何选择器更具体,只要它可能没有ID,例如。
比较算法:
更重要的说明:
- 通用选择器
的伪阶级弟兄(*)
没有特异性值(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
浏览器执行以下操作:
a
元素。li
类的.active
元素的祖先(这是通过后代组合器:ancestor descendant
)。ul
,其ID为#nav
(同样,使用了后代组合子)。如果某个元素满足所有这些条件,则将样式应用于它。
你可以阅读:
选择任何
a
元素
一个类为.active
的祖先,也是li
,
它的祖先ID为#nav
,也是ul
。
您需要拥有一个功能齐全且完整的DOM树才能成功确定哪个元素具有哪些CSS样式。