如何计算 CSS 选择器的权重?

之前在编写 CSS 的时候,多次遇到类选择器“无效”(优先级不够)的情况,例如下面的 HTML 代码:

<div class="entry">
    <p>段落内容。
        <a class="links" href="http://fengyouyi.com">链接</a>
    </p>
</div>

对应 CSS 代码如下:

.entry a {
    color: red;
}
.links {
    color: blue;
}

一直以来都简单地按照先后顺序来理解,以为这里链接会呈现蓝色,事实不然。我所理解的先后顺序,只是样式表的层叠顺序。在具体执行时,还需要考虑到样式的权重(原文作 specificity,我个人理解为权重)。

参考官方 CSS2.1 文档中的《6.4.3 Calculating a selector’s specificity》部分,我们可以了解到权重计算遵循以下规则:

  • 如果是通过 ‘style’ 属性声明而不是通过选择器来声明的规则,算作 1,否则为 0 (a 位)(在 HTML 中,一个元素的“style”属性的值是一组样式规则。这些规则没有选择器,所以 a=1、b=0、c=0、d=0);
  • 计算选择器中的 ID 属性个数(b 位);
  • 计算选择器中的其它属性(选择器)和伪类个数(c 位);
  • 计算选择器中的元素名和伪元素个数(d 位)。

这个计算方法仅基于选择器的形式。需要特别说明的是,“[id=p33]”形式的选择器是算作属性选择器的(a=0, b=0, c=1, d=0),即使在源文档的 DTD 中 id 属性被定义为“ID”。

将四个数字串联成 a-b-c-d ,就可以获得选择器的权重了。

我们要如何理解这个呢?其实很简单。所有的选择器的权重都用 a-b-c-d 的形式表示,我们只要按照从 a 到 d 四个位置的数字,对应比较就可以得到权重顺序了。例如 1-0-0-0 的权重高于 0-2-1-2 ,因为在 a 位置,前者为 1 ,后者为 0 ,这样后面的就无须比较了。

更新

2009-10-21 23:38

看到 junp 在这里的评论,我才醒悟过来,他给我参考的那篇文章中那句“HTML标记的权重是 1,CLASS的权重是 10,ID的权重是 100,继承的权重为 0 ”,使我误以为作者将这几组值当作十进制来处理了。这里,如果按照 a-b-c-d 的形式,我们需要将其理解为“HTML标记的权重是 0-0-0-1,CLASS的权重是 0-0-1-0,ID的权重是 0-1-0-0,继承的权重为 0-0-0-0 ”。所以最底部的那部分更新内容,就当作加深了解的范例吧。

对原作者飘零雾雨表示歉意,同时也对 junp 表示由衷的感谢。

2009-10-21 14:22

站长资讯论坛上的 junp 给了我一篇网络上的文章,也是介绍这个的。但是看了作者计算权重的方法,好像是不正确的。因为按照他的方式,得到的最终权重值是 a*1000 + b*100 + c*10 + d 。这个是不正确的。我们可以构想一下,如果两个选择器,A 在 d 位上有 11 个元素名,例如 div div div div div div div div div div div ,而 B 在 c 位上只有 1 个属性选择器,例如 p[id="p33"] ,按照他的计算方式,A 的权重为 11 ,B 的权重为 10 。参考下面 HTML 和 CS 代码:

<div>
  <div>
    <div>
      <div>
        <div>
          <div>
            <div>
              <div>
                <div>
                  <div>
                    <div>
                      <p id="p33">看看文本显示的颜色</p>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
div div div div div div div div div div div {
    color: red;
}
p[id="p33"] {
    color: blue;
}

结果是蓝色。

所以权重的计算,是按“位”比较,而不是十进制的。不过作者也提到了“按照从左到右的顺序逐位比较”,或许只是表述不清吧。

6 条评论

  1. To junp:

    你列出来的那个没有错的。我已经了解你说的意思。

    我想我可能是理解错了作者说的:

    HTML标记的权重是1,CLASS的权重是10,ID的权重是100,继承的权重为0 。

    我将这里的 10 和 100 理解为了十进制的十和一百。或许作者要表达的正如你列出来的,是 0-0-1-0 和 0-1-0-0 。

    • To junp:

      的确是不太合适,稍后我修改一下,直接链接到发布表单。

      这个主题没有正式完成,需要修改的地方很多,如果看到其它不合适或者需要改进的地方,请告诉我。

      谢谢!

      :)

发表评论

电子邮件地址不会被公开。 必填项已用 * 标注

*

您可以使用这些 HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>