6

我想知道在以下情况下一个有效的算法是什么:

给定一组解析的 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>我的文档中的 a)。

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

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

浏览器引擎如何有效地做到这一点?我希望在 Java 中复制它,但我对许多其他语言感到满意,因此您可以提供的任何代码都非常感谢。

谢谢

4

1 回答 1

10

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

特异性计算

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

从最具体到最不具体的排名:

  1. 样式属性 - 如果在样式属性中找到规则,则此排名为 1。
  2. ID - 对于在选择器中找到的每个 ID,此排名会额外增加 1。
  3. 类、伪类、属性选择器 - 对于在选择器中找到的每个选择器,此等级会额外增加 1。
  4. 元素 - 对于在选择器中找到的每个元素,此排名会额外增加 1。

在哪里rank n > rank n+1,无论每个等级有多少分。

例子

ul#nav li.active a

要点是:

  1. 0 - 不是样式属性。
  2. 找到 1 - 1 个 ID。
  3. 找到 1 - 1 个类名。
  4. 找到 3 - 3 个元素。

因此,该选择器中的每个属性都有一个特异性值[0,0,1,1,3](我们将在一分钟内得到那个额外的零)。该值比任何选择器都更具体,只要它可能是,例如,没有 ID。

比较算法:

  1. 在行列上从左到右。
  2. 比较两个选择器的排名。
  3. 得分较高的等级获胜。
  4. 如果排名相等,则继续向右下一个(不太具体的)排名。
  5. 如果所有等级都相等,则在 CSS 文档中较晚出现的那个将获胜

更重要的注意事项:

  • 通用选择器(*)没有特异性值 (0,0,0,0) 伪元素(例如:first-line0,0,0,1与它们的
    伪类兄弟不同0,0,1,0
  • 伪类:not()本身并没有添加任何特殊性,只有括号内的内容。
  • !important指令可以应用于单个声明,并在“0th”等级上添加一个点,这比其他任何东西都更具体
    。因此,在上面的示例中,添加!important任何规则只会将该规则
    的特异性值提高[1,0,1,1,2]
    从而使其立即胜过没有 的任何其他规则!important

额外参考

请参阅有关该主题的这篇精彩文章


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

浏览器这样做的方式是从右到左遍历选择器,并在元素移动时从 DOM 中过滤元素。

回到前面的例子:

    ul#nav li.active a

浏览器执行以下操作:

  1. 取一个a元素。
  2. 现在检查它是否有一个li带有.active类的元素的祖先(这是通过后代组合器:)ancestor descendant
  3. 现在检查它是否有一个更高的祖先,它ul的 ID 为#nav(同样,使用了后代组合器)。

如果某个元素满足所有这些条件,则将样式应用于它。

你可以阅读它:

选择 具有类为 的祖先的任何a元素,该类也是 a , 而后者又具有 ID 为 的祖先,这也是 a 。
.activeli
#navul

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

于 2012-10-05T09:47:17.543 回答