1. 什么是“选择器权重”
CSS 权重是浏览器用来决定 当多个 CSS 规则作用于同一个元素时,哪一个规则优先级更高、会被应用 的机制。 在 CSS 中,我们通过“选择器”来指定要改变哪些元素的样式。 但当 多个样式 同时作用在同一个元素上时,就会产生“冲突”。 例如:
p { color: blue; }
p { color: red; }
浏览器怎么知道 p 应该是蓝色还是红色呢? 这时候就靠 选择器权重 来决定——权重高的规则会“赢”,最终生效。
2. 选择器权重的生活类比
| 类比对象 | CSS 选择器类型 | 举例 | 权重 |
|---|---|---|---|
| 皇帝 🏯 | 行内样式(HTML 元素上直接写 style) | <p style="color:red"> | 1000 |
| 大臣 👑 | ID 选择器 | #title {} | 100 |
| 官员 🧰 | 类选择器 / 属性选择器 / 伪类 | .btn {}、[type=text]、:hover | 10 |
| 小兵 🪖 | 元素选择器 / 伪元素 | div {}、::after | 1 |
| 百姓 🙋♂️ | 通配符 / 继承样式 | * {}、继承来的 | 0 |
3. 权重计算规则
浏览器内部会把一个选择器的权重拆成四个部分,通常用一个四位数表示,a-b-c-d:
行内样式 > ID > 类/伪类/属性 > 标签/伪元素
每种选择器对应一个“分值”,按照以下方式计算:
| 位数 | 选择器类型 | 权重 |
|---|---|---|
a | 行内样式 | 1000 |
b | 每个 ID 选择器 | +100 |
c | 每个 类 / 属性 / 伪类 选择器 | +10 |
d | 每个 元素 / 伪元素 选择器 | +1 |
| 通配符(*)和继承样式 | +0 |
最后,比较数值大小即可:谁大,谁生效。这里需要注意以下几点
- 通配符(*)和继承样式不参与权重计算
- 这里的权重数值是为了便于计算和理解设置的数值,在浏览器实际的计算比较时:从左到右逐位比较,高位优先,即
a>>b>>c>>d
4. 常见例子
| 选择器 | 权重计算(a-b-c-d) | 结果 |
|---|---|---|
div | 0-0-0-1 | 1 |
.box | 0-0-1-0 | 10 |
#main | 0-1-0-0 | 100 |
div.box | 0-0-1-1 | 11 |
#main .box | 0-1-1-0 | 110 |
div p strong | 0-0-0-3 | 3 |
.nav li.active a:hover | 0-0-3-2 | 32 |
<div style="color:red"> | 1-0-0-0 | 1000(最高) |
5. 特殊情况说明
1. !important 是“尚方宝剑”
不论权重多少,只要你加上 !important,它就会强制生效。
最高优先级(仅次于内联样式中的 !important)
p { color: blue !important; } /* 1 */
#title { color: red; } /* 100 */
即使 #title 权重更高,!important 的蓝色仍然胜出。
2. 内联样式中的 !important
最高优先级,无法被覆盖
<p style="color: blue !important">文本</p>
即使外部有 !important 也无法覆盖
6. 权重冲突解决顺序(CSS 层叠规则)
当多个规则冲突时,浏览器按以下顺序决定优先级:
!important(开发者强制)- 权重(Specificity)(选择器复杂度)
- 源代码顺序(后写的覆盖先写的)
- 继承(从父元素继承的样式) 简记:important > 权重 > 顺序 > 继承
7. 实战练习
HTML:
<a href="#" style="color: yellow">链接</a>
CSS:
#main .nav a:hover { color: red; } /* A */
body div a { color: blue; } /* B */
a { color: green !important; } /* C */
最终颜色是:绿色 我们先逐步分析:
-
html中 有一个 行内样式(
style="color: yellow"),权重为1-0-0-0,权重值为 1000 -
css中 设置了3条规则
- 规则A,
#main .nav a:hover,权重为0-1-2-1,权重值为121,设置颜色为红色 - 规则B,
body div a,权重为0-0-0-3,权重值为 3,设置颜色为蓝色 - 规则C,
a,权重为0-0-0-1,权重值为 1,这里需要注意 **设置了!important**,设置颜色为绿色
- 规则A,
权重比较逻辑:
-
首先看有没有
!important- 只有 C(绿色) 有
!important→ 它直接进入最高优先级组
- 只有 C(绿色) 有
-
行内样式 vs !important
!important的优先级 > 行内样式(没有 important)- 所以即使行内
style="color: yellow"权重是 1000,也会被 C 的!important覆盖
-
其他 A、B 两条规则都没有
!important,自然也被排除
最终生效的样式:
绿色(来自 a { color: green !important; })
8. 总结
- 有
!important→ 优先级最高;若有多个!important,再比权重,再比加载顺序 - 没
!important→ 比权重(行内样式 > ID > 类/伪类/属性 > 标签/伪元素) - 权重相同 → 后定义的覆盖前定义的
- 都没定义 → 用继承或浏览器默认样式