CSS 特异性中的点是如何计算的

Posted

技术标签:

【中文标题】CSS 特异性中的点是如何计算的【英文标题】:How are the points in CSS specificity calculated 【发布时间】:2011-02-18 00:53:50 【问题描述】:

研究特异性我偶然发现了这个博客 - http://www.htmldog.com/guides/cssadvanced/specificity/

它指出特异性是 CSS 的评分系统。它告诉我们元素值 1 分,类值 10 分,ID 值 100 分。它还在上面说这些点是总计的,总量是选择器的特异性。

例如:

body = 1 分body .wrapper = 11 分body .wrapper #container = 111 分

因此,使用这些点,我希望以下 CSS 和 HTML 会导致文本为蓝色:

#a 
    color: red;


.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o 
  color: blue;
<div class="a">
  <div class="b">
    <div class="c">
      <div class="d">
        <div class="e">
          <div class="f">
            <div class="g">
              <div class="h">
                <div class="i">
                  <div class="j">
                    <div class="k">
                      <div class="l">
                        <div class="m">
                          <div class="n">
                            <div class="o" id="a">
                              This should be blue.
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

为什么 15 个类等于 150 分,而 1 个 ID 等于 100 分,文本是红色的?

显然,分数不只是总计;它们是串联的。在此处阅读更多相关信息 - http://www.stuffandnonsense.co.uk/archives/css_specificity_wars.html

这是否意味着我们的选择器中的类 = 0,0,15,0 OR 0,1,5,0

(我的直觉告诉我是前者,因为我们知道 ID 选择器的特殊性如下所示:0,1,0,0

【问题讨论】:

这里也有一些奇怪的地方:***.com/questions/25565928/… 【参考方案1】:

Pekka's answer实际上是正确的,并且可能是思考这个问题的最佳方式。

然而,正如许多人已经指出的那样,W3C CSS 建议指出“连接三个数字 a-b-c(在具有大基数的数字系统中)具有特异性。”所以我的极客只需要弄清楚这个基地有多大。

事实证明,用于实现此标准算法的“非常大的基数”(至少由 4 个最常用的浏览器*)是 256 或 28.

这意味着用 0 个 id 和 256 个类名指定的样式覆盖只用 1 个 id 指定的样式。我用一些小提琴对此进行了测试:

255 classes are not enough to override 1 id

...but 256 classes are enough to override 1 id

...and 256 tag-names are enough to override 1 class-name

...but, alas 256 ids are not enough to override 1 inline style(2012/8/15 更新——你必须使用!important

所以实际上有一个“积分系统”,但它不是以 10 为底,而是以 256 为底。它的工作原理如下:

(28)2 或 65536,乘以选择器中的 id 数

(28)1 或 256,乘以选择器中的类名数 (28)0 或 1,乘以选择器中的标记名称数

这对于传达概念的粗略练习不是很实用。 这可能是有关该主题的文章一直使用基数 10 的原因。

***** [Opera 使用 216(参见 karlcow 的评论)。其他一些选择器引擎使用 infinity - 实际上没有积分系统(参见 Simon Sapin 的评论)。]

2014 年 7 月更新: 正如 Blazemonger 在今年早些时候指出的那样,webkit 浏览器(Chrome、Safari)现在使用的基数似乎高于 256。也许 216,比如 Opera? IE 和 Firefox 仍然使用 256。

2021 年 3 月更新: Firefox 不再使用 256 作为基础。

【讨论】:

重要提示:数字 256 不在 spec 中。因此,这个答案描述了一个(公认有用的)实现细节。 正如@MattFenwick 所说,不仅 256 不在规范中,而且在实施过程中也有所不同。它在 Opera 中显然更大。在 WeasyPrint 和 cssselect 中,它是“无穷大”:我使用 a tuple of integers 而不是单个整数。 @Faust Opera 使用 16 位而不是 8 位 老实说,这个答案比 Pekka 的答案更实用。基本上@Matt Fenwick 所说的:您所描述的是规范的实际实现。一个有缺陷的,但不应该做任何事情,无论是作者还是实施者。 256 在当前版本的 webkit(Chrome 和 Safari)中似乎不足,进一步强调了 @MattFenwick 的观点。【参考方案2】:

好问题。

我不能确定 - 我设法找到的所有文章都避免了多个类的示例,例如here - 但我假设在比较类选择器和 ID 之间的特异性 时,无论它有多详细,该类仅使用 15 的值进行计算。

这符合我在特异性表现方面的经验。

但是,必须有一些类的堆叠,因为

.a .b .c .d .e .f .g .h .i .j .k .l .m .n .o

比更具体

.o

我唯一的解释是堆叠类的特异性仅根据彼此计算,而不是根据 ID。

更新:我现在知道一半了。它不是积分系统,关于重 15 分的班级的信息是不正确的。这是一个由 4 部分组成的编号系统,很好地解释了 here。

起点是4位数字:

style  id   class element
0,     0,   0,    0

根据W3C explanation on specificity,上述规则的具体值为:

#a            0,1,0,0    = 100
classes       0,0,15,0   = ... see the comments

这是一个具有非常大(未定义?)基数的编号系统。

我的理解是,因为基数很大,第4列没有一个数可以胜过第3列>0的数,第2列也是一样,第1列……这样对吗?

我很想知道是否有人比我更精通数学,能否解释编号系统以及当单个元素大于 9 时如何将其转换为十进制。

【讨论】:

那是因为它在 .o 和 .a .b 等之间所以它会一起考虑它们。但是在 ID 和类之间,例如:.a 和 #a,ID 总是会压倒一切。当没有更强大的属性时,它(我假设)只会在类之间计算。例如,class 会遍历元素,id 会遍历类。 @Ozaki 这也是我的假设,但这与 OP 关于积分系统的说法相矛盾。必须有更多的游戏。我想看看它背后的规则。 刚刚意识到我们都得出了相同的结论。干得好! 在数学方面,我们可以在这里以 16 为基数工作(因为没有一个数字超过 15)。所以 0,1,0,0 = 0100h = 256 0,0,15,0 = 00f0h = 240 256 > 240 所以 id 选择器获胜。 是的,您可以将特异性计算视为在具有大基数的数字系统中完成。我认为术语“连接”(也在规范中使用)是一个更好的描述。 (从回答一个新问题来到这里,结果证明是这个问题的欺骗,去看看......)【参考方案3】:

当前的Selectors Level 4 Working Draft 很好地描述了 CSS 中的特异性:

特异性是通过依次比较三个分量来比较的:A值越大的特异性越特异性;如果两个A值并列,则B值越大的特异性越具体;如果两个 B 值也并列,则 c 值越大的特异性越具体;如果所有值都相同,则两个特性相等。

这意味着值 A、B 和 C 完全相互独立。

15 个类不会给您的选择器 150 的特异性得分,它给它的 B 值为 15。单个 A 值足以压倒它。

作为一个比喻,想象一个有 1 个祖父母、1 个父母和 1 个孩子的家庭。这可以表示为1,1,1。如果父母有 15 个孩子,那不会突然让他们成为另一个父母 (1,2,0)。这意味着父母比他们只有 1 个孩子承担的责任要多得多 (1,1,15)。 ;)

同样的文档还继续说:

由于存储限制,实现可能对 ABc 的大小有限制。如果是这样,则必须将高于限制的值限制在该限制范围内,而不是溢出。

已添加此功能以解决 Faust's answer 中提出的问题,即 2012 年的 CSS 实现允许特异性值相互溢出。

早在 2012 年,大多数浏览器都实现了 255 的限制,但这个限制被允许溢出。 255 个类的 A,B,c 特异性分数为 0,255,0,但 256 个类溢出并具有 A,B,c 分数1,0,0。突然间,我们的 B 值变成了我们的 A 值。 Selectors Level 4 文档通过声明永远不允许溢出来完全解决这个问题。通过此实现,两个 255 和 256 类将具有相同的 A,B,c 分数 0,255,0

Faust 的回答中给出的问题已经在大多数现代浏览器中修复

【讨论】:

【参考方案4】:

我目前正在使用本书CSS Mastery: Advanced Web Standards Solutions。

第 1 章第 16 页说:

要计算规则的具体程度,会分配每种类型的选择器 一个数值。然后计算规则的特异性 将每个选择器的值相加。 不幸的是, 特异性不是以基数 10 计算的,而是一个高的、未指定的基数 数字。这是为了确保高度特定的选择器,例如 ID 选择器,永远不会被许多不太具体的选择器覆盖, 例如类型选择器。

(强调我的)和

选择器的特殊性分为四个组成部分 级别:a、b、c 和 d。

如果样式是内联样式,则 a = 1 b = id 选择器的总数 c = 类、伪类和属性选择器的数量 d = 类型选择器和伪元素选择器的数量

接着说,您通常可以以 10 为底进行计算,但前提是所有列的值都小于 10。


在您的示例中,id 不值 100 分;每个都值得[0, 1, 0, 0] 点。因此,一个 id 胜过 15 个类,因为在高基数系统中,[0, 1, 0, 0] 大于 [0, 0, 15, 0]

【讨论】:

【参考方案5】:

我喜欢将特异性排名与奥运会奖牌榜进行比较(金牌优先法 - 首先基于金牌数量,然后是银牌,然后是铜牌)。

它也适用于您的问题(一个特异性组中有大量选择器)。特异性分别考虑每个组。在现实世界中,我很少看到有十几个选择器的情况。

here 也有相当不错的特异性计算器。您可以将示例(#a 和 .a .b .c .d .e .f .g .h .i .j .k .l .m .n .o)放在那里并查看结果。

2016 年里约奥运会奖牌表示例如下

【讨论】:

【参考方案6】:

我不相信博客的解释是正确的。规范在这里:

http://www.w3.org/TR/CSS2/cascade.html#specificity

类选择器中的“点”加起来不能比“id”选择器更重要。它只是不能那样工作。

【讨论】:

就像我在回答中所说的那样。 ^^ 但是,如果您有更多相同类型(元素、类、id),它确实会有所不同。但如果 5things 说红色和 3 说蓝色好,那就很明显了,我会变红。 关于特异性的措辞在 CSS2 和 CSS2.1 之间可能没有太大变化,但你真的应该在未来的讨论中指出 CSS2.1 规范,因为它完全取代了通常被破坏的 CSS2在发布时。【参考方案7】:

我会说:

Element < Class < ID

我认为,如果它是相同的倍数,它们只会叠加到你得到的结果中。 所以一个类总是会覆盖元素,ID 总是覆盖类,但是如果它是 4 个元素中的哪一个,其中 3 是蓝色,1 是红色,它将是蓝色的。

例如:

.a .b .c .d .e .f .g .h .i .j .k .l

color: red;


 .m .n .o

color blue;

应该变成红色。

见Example http://jsfiddle.net/RWFWq/

“如果 5 件事说红色,3 件事说蓝色,那我就红了”

【讨论】:

以上是关于CSS 特异性中的点是如何计算的的主要内容,如果未能解决你的问题,请参考以下文章

ROC曲线 大于阈值后如何计算HR

如何计算多类总体准确度、敏感性和特异性?

C语言中的序列点是啥意思

Css权威指南(4th,第四版中文翻译)-3.特异性和层级继承

Python中的点是啥? [复制]

了解 CSS 选择器优先级/特异性