特异性权重是CSS中决定样式优先级的四元组(a,b,c,d),按千百十个位逐级比较,高位相等才比低位;ID选择器加b位、类/伪类/属性选择器加c位、元素/伪元素选择器加d位,内联样式为(1,0,0,0),!important不改变权重但绕过比较流程。

什么是特异性权重,它不是“谁写在后面就赢”
浏览器不会按CSS文件里规则出现的先后顺序来决定样式生效与否。真正起作用的是每个选择器的特异性(specificity)——一个由四部分组成的数值,形如 (a, b, c, d)。它像四位数一样从左到右比较大小,a 是千位,b 是百位,以此类推,**高位相等才看低位,不存在进位**。
常见误解是“多个 class 加起来能干掉一个 ID”,这是错的:#nav 是 (0, 1, 0, 0),而 .a.b.c.d.e 是 (0, 0, 5, 0),前者仍远高于后者。
#header .nav a:hover 的权重怎么算
拆解这个选择器:一个 ID(#header)、一个类(.nav)、一个元素(a)、一个伪类(:hover)。按规则归类:
- ID 选择器 →
b = 1 - 类选择器 →
c = 1 - 元素选择器 →
d = 1 - 伪类选择器 →
c += 1(注意:伪类和类共用c位)
所以最终是 (0, 1, 2, 1)。不是“加起来=4”,而是“百位为1、十位为2、个位为1”。
对比 div#main ul.menu li.active a:ID ×1(b=1),类 ×1(c=1),元素 ×4(d=4)→ (0, 1, 1, 4)。虽然 d 更大,但 c 位 2 > 1,所以前者胜出。
属性选择器和伪元素的权重容易被低估
[type="submit"] 和 :hover 都属于第三级(c 位),各贡献 1;而 ::before 属于第四级(d 位),只算 1。这点常被忽略,导致误判。
例如:
-
input[type="text"]→(0, 0, 1, 1) -
.form-input→(0, 0, 1, 0) -
input.form-input→(0, 0, 1, 1)(和第一条相同,此时源码顺序才起作用)
再比如 button::after 是 (0, 0, 0, 2),比单纯的 .btn((0, 0, 1, 0))权重低——因为 c=1 > d=2,哪怕后者有两个元素选择器。
!important 不参与权重计算,但它会绕过整个机制
!important 不是“权重无穷大”,而是**脱离特异性比较流程**。它不改变 (a,b,c,d) 值,而是让这条声明直接跳过层叠规则,优先应用(除非另一条也有 !important,这时才回退到比权重)。
这意味着:
-
p { color: red !important; }会覆盖#intro { color: blue; },哪怕后者是 ID 选择器 - 但
#intro { color: blue !important; }又能覆盖前者,因为两者都有!important,此时才比(0,1,0,0) > (0,0,0,1) -
style="color:green"(内联)权重是(1,0,0,0),仍会被!important覆盖
真正难调试的,往往是混用了 !important 和高特异性选择器的组合——此时得靠浏览器开发者工具的“已计算样式”面板逐条看 strike-through 状态,而不是靠心算。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











