计算CSS选择器特异性:not()伪类

时间:2013-04-08 13:04:57

标签: css css-selectors pseudo-class css-specificity

我已经知道如何计算CSS的选择器特异性(规格中提到的a / b / c / d)。但是,我无法确定如何为:not()伪类计算它。请参阅以下示例:

input:not([type="text"],[type="password"],.someClass) {...}
input:not(#someId[type="text"]) {...}

假设它们都适用于一个元素,那么这两个元素是否应该计算为(0011),因此它们应该按照出现顺序排序?或者,:not()伪类中的选择器是否应根据哪一个匹配进一步单独计算,作为第二步确定优先于另一个的选择器?

3 个答案:

答案 0 :(得分:4)

  

假设它们都适用于一个元素,那么这两个元素是否应该计算为(0011),因此它们应该按照出现顺序排序?或者,:not()伪类中的选择器是否应该根据哪一个匹配进一步单独计算,作为确定优先于另一个匹配的第二步?

如果您正在实施Selectors 3则不应将其计算在内。如前所述,根据该规范,两个选择器都是无效的,因为它只定义:not()一次接受一个简单的选择器。

如果您将它们展开以便验证(按照here给出的说明/示例),那么它们的具体情况将按如下方式计算:

/* 2 attributes, 1 class, 1 type -> specificity = 0-3-1 */
input:not([type="text"]):not([type="password"]):not(.someClass)

/* 
 * 1 ID, 1 type        -> specificity = 1-0-1
 * 1 attribute, 1 type -> specificity = 0-1-1
 */
input:not(#someId), input:not([type="text"])

因为Selectors 3 says

  

否定伪类中的选择器与任何其他类似,但是否定本身不算作伪类。

另外,回应你的评论:

  

确实,根据规格,只有简单的选择器。但有些浏览器支持多个浏览器。其中一些没有,有些人稍后放弃了。此外,即使使用像这样的简单选择器,您也可以编写相同的规则:input:not([type="text"]):not([type="password"]):not(.someClass)哪个更好,也可以正常工作。这是否意味着它应该计算为0031,那么?支持多个的那些怎么样,他们如何计算?

我知道的浏览器曾经支持:not()中的多个选择器是Firefox 3.0,并且它是因为一个错误而这样做的。选择器3 从不允许:not()包含多个选择器 - 仅在Selectors 4中引入,特殊计算尚未明确定义 1 ,所以即使你试图实现Selectors 4(我认真地怀疑你是),你也会陷入困境。

我不清楚Firefox 3.0如何使用其:not()选择器的版本实现特异性,我没有它的副本进行测试,但我认为可以安全地假设它并不重要,因为它从来都不是预期的行为。好的所以我选择了Firefox 3.0 beta 1,3.0.0,3.0.18和3.1 beta 1,并且它们都没有重现这种行为。所以你有它。


1 请注意,当前的2013 ED和2011 FPWD一致表示:not()的特异性与其最具体的参数的特异性相同,但是可能会在未来发生变化。

答案 1 :(得分:1)

逻辑意图

以下是最初在问题中发布的CSS选择器的细分。这是尝试总结如何使用有效的CSS表达CSS规则(由@thgaskell和@BoltClock开始的讨论)。我将把特异性问题留给其他海报。

第一条规则

input:not([type="text"],[type="password"],.someClass) {}

这是CSS3中的非验证选择器,目前任何已知的浏览器都不支持。

选择器的逻辑意图是!(a or b or c),相当于!a and !b and !c。对于CSS选择器,逻辑and操作需要链接,可以表示为:not(a):not(b):not(c)

因此,第一条规则可以用有效的CSS表示如下:

input:not([type="text"]):not([type="password"]):not(.someClass) {}

第二条规则

input:not(#someId[type="text"]) {}

这是CSS3中的非验证选择器,目前任何已知的浏览器都不支持。

选择器的逻辑意图是!(a and b),相当于!a or !b。对于CSS选择器,逻辑or操作需要使用多个选择器(每个操作数一个选择器),可以表示为:not(a), :not(b)

因此第二条规则可以用有效的CSS表示如下:

input:not(#someId), input:not([type="text"]) {}

摘要

逻辑and操作需要链接每个操作数。

.a.b {}                /* Matches elements with both classes  */
                       /*     (a and b)                       */

:not(.a):not(.b) {}    /* Matches elements with neither class */
                       /*     (!a and !b) == !(a or b)        */

逻辑or操作需要使用多个选择器(每个操作数一个选择器)。

.a, .b {}              /* Matches elements with either class              */
                       /*     (a or b)                                    */

:not(.a), :not(.b) {}  /* Matches elements that don't have both classes   */
                       /* (elements with none or only one of the classes) */
                       /* (aka: not both, nand, alternative denial        */
                       /*     (!a or !b) == !(a and b)                    */

答案 2 :(得分:0)

spec(W3C Selectors Level 3)非常清楚地表明伪类与类相同。

有些人在主流浏览器中使用jsfiddle表示你是正确的(在你的评论中),以及

的特异性
 input:not([type="text"]):not([type="password"]):not(.someClass) {border:3px solid red}

...将是0.0.3.1。在后来的样式声明中需要3个类名来过度规则上面的选择器。

假设:

<input value="X" class="Y Z" id="myId"/>

您不能仅使用以下方式覆盖上述选择器:

input.Y.Z{border:3px solid pink;}

请参阅http://jsfiddle.net/mhfaust/SxavM/1/

更新 BoltClock是对的。规范声明“否定伪类中的选择器与其他选择器一样,但是否定本身并不算作伪类。”因此,由于:not()内的每个选择器在本例中都是类名或伪类,因此特异性仍为0.0.3.1