之前在编写 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;
}
结果是蓝色。
所以权重的计算,是按“位”比较,而不是十进制的。不过作者也提到了“按照从左到右的顺序逐位比较”,或许只是表述不清吧。
a b c d
0 0 1 1 .entry a
0 0 1 0 .links
是不是这样?
高深的技术贴,好像我也有点看得懂,好像又看不懂。
To junp:
你列出来的那个没有错的。我已经了解你说的意思。
我想我可能是理解错了作者说的:
我将这里的 10 和 100 理解为了十进制的十和一百。或许作者要表达的正如你列出来的,是 0-0-1-0 和 0-1-0-0 。
“发表评论”的锚点是不是欠妥?
To junp:
的确是不太合适,稍后我修改一下,直接链接到发布表单。
这个主题没有正式完成,需要修改的地方很多,如果看到其它不合适或者需要改进的地方,请告诉我。
谢谢!
:)
本文说的,正好有用。