# 一、概述
每一类选择器都有自己的权重值,我们通常理解为优先级。权重值越高,则优先级越大。
CSS规则权重就是CSS规则中的选择器的权重相加得到的。
浏览器通过CSS规则权重比较,来计算出最终的层叠样式,以作用于目标元素。
举个例子
<style>
.box {
width: 100px;
height: 100px;
background-color: blue;
}
div {
background-color: red;
}
</style>
<section id="root">
<div class="box"></div>
</section>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
如上图,我们发现:CSS样式最终层叠出了蓝色的背景,我们如何让它呈现红色呢?
# 二、CSS选择器权重
我们知道 CSS样式优先级是这样的,即 !important > 内联样式 > ID > 类、伪类、属性 > 元素、伪元素 > 继承 > 通配符 。那么他们分别对应的权重值如下表。
| 选择器/关键字 | 例子 | 权重值 |
|---|---|---|
!important 关键字 | background-color: red !important; | +∞ |
| 内联样式 | style="background-color: red;" | 1000 |
| ID选择器 | #root{} | 100 |
| 类选择器、伪类选择器、属性选择器 | .red{}、:active{}、[title='name']{} | 10 |
| 标签选择器、伪元素选择器 | div{}、::first-line{} | 1 |
| 通配符、子选择器符、相邻选择器符 | *{}、>、+ | 0 |
# 三、CSS选择器权重计算规则
CSS选择器权重就是其中所有选择器的权重相加得到的。
style="" => 1000(行内样式)
#title{} => 100(一个ID)
.root => 10(一个类)
[title] => 10(一个属性)
div => 1(一个标签)
*{} => 0(通配符)
div span {} => 1+1=2(两个标签)
div h1+span {} => 1+1+1=2(三个标签,一个子选择器符)
div:first-child => 1+10=11(一个标签,一个伪类)
div [title] => 1+10=11(一个标签,一个属性)
body #title .root p {} => 1+100+10+1=112(两个标签,一个Id,一个类)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 四、总结
回头看第一小节的问题,我们有一千种方式让小方块呈现出红色。其原则就是通过设置更高权重值的CSS规则。
<style>
.box {
width: 100px;
height: 100px;
background-color: blue;
}
div {
background-color: red;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
题目中 .box 规则的权重值是 10,div 规则的权重值是 1,所以小方块最终呈现出了蓝色。
- 通过添加
ID选择器如下,权重值为 100+1=101
<style>
#root div {
background-color: red;
}
</style>
1
2
3
4
5
2
3
4
5
- 通过添加
!important关键字如下,权重值为 1+∞=∞
<style>
div {
background-color: red !important;
}
</style>
1
2
3
4
5
2
3
4
5
- 通过添加
行内样式如下,权重值为 1000
<section id="root">
<div class="box" style="background-color: red;"></div>
</section>
1
2
3
2
3
因为如上三种方案的权重值都超过了 .box 规则的权重,所以小方块呈现出了红色。
# 五、纠正错误
不知道有没有人有疑问,权重值是在W3C里定义的吗?还是笔者为了理解创造的?那么我们就应该去W3C光访问当查一下,发现真的没有定义,是胡编乱造的。其实权重比较也不是上一节中说的加和计算的。
# 5.1 统计各类选择器数量
- 计算ID选择器的数量为 A
- 计算类选择器、属性选择器、伪类选择器的数量为 B
- 计算元素选择器、伪元素选择器数量为 C
- 忽略通用选择器
特殊场景需要特别注意:
- 伪类选择器 :is()、:not()、:has() 特异性为参数选择器列表中,特异性最高的选择器特异性
- 伪类选择器 :nth-child(An+B [of S]?)、:nth-last-child(An+B [of S]?) 特异性为参数选择器列表中,特异性最高的选择器特异性叠加普通伪类选择器特异性
- 伪类选择器 :where() 特异性为 0
# 5.2 比较CSS选择器权重
- A值越大的权重值越强;
- 如果两个A值相同,则B值越大的权重越高;
- 如果两个B值也相同,则C值越大的权重越高;
- 如果所有值都一样,则这两个权重相同。
需要特别注意的是,行内样式的权重最高。
# 5.3 属性来源优先级排序
- Transition declarations (过渡)
- Important user agent declarations (浏览器预设 !important)
- Important user declarations (用户预设 !important)
- Important author declarations (开发人员 !important)
- Animation declarations (动画)
- Normal author declarations (开发人员)
- Normal user declarations (用户预设)
- Normal user agent declarations (浏览器预设)