高效算法比较CSS规则的特异性 [英] Efficient Algorithm To Compare Specificity Of CSS Rules

查看:123
本文介绍了高效算法比较CSS规则的特异性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



给出一组css规则,例如

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

set应用于给定的元素(例如我的文档中的< p class =pStyle anotherPStyle> hello< / p> )。



我需要确定样式表中的哪些规则首先适用于给定的元素(因此这里是 p,pStyle和anotherPStyle ),然后创建一个Comparator,它能够通过特异性(从最特定到最常用)对适用的规则进行排序。注意:我已经设计了一个算法来应用规则一旦排序,所以你不需要有效地解决这个问题。



我一直在玩几个想法,包括确定DOM树中给定规则特定的级别....虽然我不确定这是否是正确的方式?



浏览器引擎如何有效地执行此操作?我希望在Java中复制它,但是很多其他语言很方便,所以您可以提供的任何代码都非常感激。



感谢

解决方案

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



特异性计算


$ b b

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



从最具体到最少排序:


  1. 样式属性 -

  2. ID - 对于在选择器中找到的每个ID,此排名将获得额外的1。

  3. 类,伪类,属性选择器 - 对于在选择器中找到的每一个,这个等级获得额外的1。

  4. 元素 - 对于在选择器中找到的每个元素,附加1。

其中 rank n>



示例



ul#nav li.active a


$ b b

要点是:


  1. 0 - 不是样式属性。

  2. 找到1个ID。

  3. 1 - 1找到类别。

  4. 找到3 - 3个元素。

因此,该选择器中的每个属性具有 [0,0,1,1,3] 的特异性值(We'我会在一分钟得到那个额外的零)。



比较算法:


  1. 在排名上从左到右。

  2. 比较两个选择器上的排名。


  3. 如果等级相等,则继续直到下一个(较不具体)等级。

  4. >如果所有等级都相等,那么CSS文档中稍后的一个会赢得




更重要的注意事项:




  • 通用选择器(*)没有特异性值(0,0,0,0)伪元素(例如:一行)get 0,0,0, 1 不同于他们的

    伪类兄弟,它们得到 0,0,1,0

  • 伪类:not()本身并不添加特殊性,只添加括号内的内容。

  • !important 指令可以应用于单一声明,并将一个点添加到0排名,这比任何更具体

    else。因此,在上面的示例中,对任何规则添加!important

    将特定值仅限于 code> [1,0,1,1,2]


    授予它立即赢过任何其他规则,而不!important



额外参考



请参阅 这篇精彩文章 关于主题






如何确定哪些样式到什么元素



浏览器执行此操作的方式是从从右到左翻阅选择器,然后在DOM中过滤元素。



返回上一个示例:

  ul#nav li.active a 

浏览器执行以下操作:


  1. a 元素。

  2. 现在检查它的祖先是否为 li 元素与 .active 类(这是通过后代组合符: ancestor descendant )。

  3. 现在检查它是否有高于的祖先是 ul ,ID为# nav (再次使用后代组合器)。

如果满足所有这些条件



您可以阅读:


选择任何 a 元素

,其祖先类型为 .active 也是 li

,其又具有ID为 #nav 的祖先, ,也是 ul


完全功能和完整的DOM树,以便能够成功地确定哪个元素有什么CSS样式。


I was wondering what an efficient algorithm would be in the following scenario:

Given a parsed set of css rules, eg.

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

from a css stylesheet, it is possible that several rule sets apply to a given element (say a <p class="pStyle anotherPStyle">hello</p> in my document).

I need to determine what rules in the stylesheet apply to a given element firstly (so here that is p, pStyle and anotherPStyle), and then create a Comparator that is able to sort the applicable rules by specificity (from most-specific to most-general). NOTE: I already have designed an algorithm to apply the rules once sorted so you needn't solve that problem efficiently.

I've been toying with several ideas, namely one that involves determining the level in the DOM tree that a given rule is specific to....Though I'm not sure if this is the correct way to go?

How does the browser engine do this efficiently? I'm looking to replicate it in Java, but am comfortable with many other languages so any code you can offer is most appreciated.

Thanks

解决方案

That is determined by specificity. In this case, since they are both equally specific, the declaration that comes last in the file, wins.

Specificity Calculation

Specificity is calculated by ranking the different parts of the selector.

Ranked from most specific to least:

  1. Style attribute - If the rule is found in a style attribute, this rank gets 1.
  2. ID - For each ID found in the selector, this rank gets an additional 1.
  3. Classes, Pseudo-Classes, Attribute selectors - For each one found in the selector, this rank gets an additional 1.
  4. Elements - For each element found in the selector, this rank gets an additional 1.

Where rank n > rank n+1, regardless of how many points each rank has.

Example

ul#nav li.active a

The points are:

  1. 0 - Not a style attribute.
  2. 1 - 1 ID found.
  3. 1 - 1 Classname found.
  4. 3 - 3 Elements found.

Therefore, each property in that selector has a specificity value of [0,0,1,1,3] (We'll get to that extra zero in a minute). That value is more specific than any selector, as long as it might be, without an ID, for example.

Comparison algorithm:

  1. Go from left to right on the ranks.
  2. Compare the ranks on both selectors.
  3. The rank with the higher amount of point, wins.
  4. If the ranks are equal, continue right to the next (less specific) rank.
  5. If all ranks are equal, the one which comes later in the CSS document, wins.

More important notes:

  • The universal selector (*) has no specificity value (0,0,0,0) Pseudo-elements (e.g. :first-line) get 0,0,0,1 unlike their
    pseudo-class brethren which get 0,0,1,0
  • The pseudo-class :not() adds no specificity by itself, only what's inside it's parentheses.
  • The !important directive can be applied on a single declaration, and adds a point to a "0th" rank, which is more specific than anything
    else. So in the example above, adding !important on any rule will
    bump the specificity value for that rule only to [1,0,1,1,2],
    granting it an instant win over any other rules without !important.

Extra Reference

See this great article on the subject


How to determine which styles go to what element

The way the browser does it, is to go over the selector from right to left, and filtering elements out of the DOM as they go.

Going back to the previous example:

    ul#nav li.active a

The browser does the following:

  1. Take an a element.
  2. Now check if it has an ancestor that is a li element with an .active class (this is through the descendant combinator: ancestor descendant).
  3. Now check if it has a higher ancestor that is a ul with an ID of #nav (again, the descendant combinator is used).

If all these conditions are met for a certain element, then the styles are applied to it.

You can read it:

Select any a element
with an ancestor with a class of .active, which is also a li,
which in turn has an ancestor with an ID of #nav, which is also a ul.

You'll need to have a fully function and complete DOM tree to be able to successfully determine which element has what CSS styles.

这篇关于高效算法比较CSS规则的特异性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆