权重值的计算
在最开始学习 CSS 的时,由于自己对 CSS 权重计算认识还很模糊的,在编码的时候单纯的堆积选择器数量来实现样式覆盖,导致代码非常臃肿不利于维护或者经常会疑惑某条 CSS 规则为何没有生效。正所谓“基础不牢,地动山摇”,今天就来好好回顾回顾 CSS 权重的基础。
其实计算规则在 W3C 规范中有解释:
- count 1 if the declaration is from is a 'style' attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element's "style" attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
- count the number of ID attributes in the selector (= b)
- count the number of other attributes and pseudo-classes in the selector (= c)
- count the number of element names and pseudo-elements in the selector (= d)
翻译成中文如下:
- 如果规则是写在标签的style属性中(内联样式),则 A=1,否则 A=0。对于内联样式,由于没有选择器,所以 B、C、D 的值都为 0,即 A=1, B=0, C=0, D=0(简写为 1,0,0,0,下同)。
- 计算该选择器中ID的数量。(例如,
#header
这样的选择器,计算为 0, 1, 0, 0)。 - 计算该选择器中伪类及其它属性的数量(包括类选择器、属性选择器等,不包括伪元素选择器)。 (例如
.logo[id='site-logo'
] 这样的选择器,计算为 0, 0, 2, 0)。 - 计算该选择器中伪元素及标签的数量。(例如,p:first-letter 这样的选择器,计算为0, 0, 0, 2)。
W3C 还给出了更为详细的实例解析:
* {} /* a=0 b=0 c=0 d=0 -> specificity = 0, 0, 0, 0 */
li {} /* a=0 b=0 c=0 d=1 -> specificity = 0, 0, 0, 1 */
li:first-line {} /* a=0 b=0 c=0 d=2 -> specificity = 0, 0, 0, 2 */
ul li {} /* a=0 b=0 c=0 d=2 -> specificity = 0, 0, 0, 2 */
ul ol+li {} /* a=0 b=0 c=0 d=3 -> specificity = 0, 0, 0, 3 */
h1 + *[rel=up]{} /* a=0 b=0 c=1 d=1 -> specificity = 0, 0, 1, 1 */
ul ol li.red {} /* a=0 b=0 c=1 d=3 -> specificity = 0, 0, 1, 3 */
li.red.level {} /* a=0 b=0 c=2 d=1 -> specificity = 0, 0, 2, 1 */
#x34y {} /* a=0 b=1 c=0 d=0 -> specificity = 0, 1, 0, 0 */
style="" /* a=1 b=0 c=0 d=0 -> specificity = 1, 0, 0, 0 */
所以很多人将上述规则总结成下表:
选择器 | 表达式或者示例 | 权重 | 说明 | specificity |
---|---|---|---|---|
内联样式 | style="" |
1000 | inline style | [1,0,0,0] |
ID选择器 | #IdSelector |
100 | id selectors | [0,1,0,0] |
类选择器 | .class-selector |
10 | class selectors | |
属性选择器 | [title=""] |
10 | attributes selectors | |
伪类选择器 | :first-child |
10 | pseudo-classes selectors | |
伪元素选择器 | p:first-letter |
1 | pseudo-elements selectors | |
标签选择器 | div |
1 | type selectors |
从单个样式选择器来看 CSS 权重优先级,我们可总结出如下公式:
!important
> 内嵌样式 > ID选择器(#id
) > class选择器(.class
) > 标签选择器、伪类选择器、属性选择器 > 伪元素 > 通配符选择器(*
) >继承(inherit
)。
CSS 规则包含多个选择器情况,以下的选择器应拆分为两个选择器再计算
选择器 | 表达式或者示例 | 说明 |
---|---|---|
相邻选择器 | selecter + selecter |
|
兄长选择器 | selecter ~ selecter |
|
亲子选择器 | selecter > selecter |
|
后代选择器 | selecter selecter |
如果数值还是很抽象的话,那么下图更加直观的展示了 CSS 权重是如何计算的:
这样量化权重值之后,很直观,但是权重值不是 10 进制的也不会进位,不要以为 11 个 class
选择器就能抵得过一个 id
选择器。我们可以用以下代码作为测试:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>11 class selector Vs 1 id selector</title>
<style type="text/css">
/* 一个id 选择器 */
#testId {
color: yellow;
}
/* 11个class 选择器 */
.test .test .test .test .test .test .test .test .test .test .test {
color : red;
}
</style>
</head>
<body>
<div class="test">
<div class="test">
<div class="test">
<div class="test">
<div class="test">
<div class="test">
<div class="test">
<div class="test">
<div class="test">
<div class="test">
<div class="test" id="testId">
看我颜色
</div><!-- 11个嵌套的 div -->
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
结果也验证了,上述猜想是错误的,最终结果文字颜色是红色的。
在某些浏览器中 256 个类选择器的却能干的过一个ID选择器,但是这只是一个Bug。
!important
!important