header 比 .header 更优先,因为其权重为 (0,1,0,0),而 .header 为 (0,0,1,0),id 选择器(b位)高于类选择器(c位),高位已定胜负。

为什么 #header 比 .header 更优先?不是“个数多就赢”
因为 CSS 权重不是算总分,而是按位比大小:ID 选择器占的是第二高位(b位),类选择器只占第三位(c位)。只要 b > 0,哪怕后面跟 99 个类、999 个标签,也完全没机会比——高位已定胜负。
-
#nav .item权重是(0,1,1,0),而.nav .item .active div span是(0,0,3,5),前者胜出 - 嵌套再深、类名再多,
c和d再大也超不过b=1,就像百位数永远大于任何十位数 - 浏览器比较时根本不会算到第三位,看到
b=1 > b=0就直接停手
怎么快速算出一个选择器的权重?盯住 (a,b,c,d) 四位
别加总、别进位、别猜深度——只数四类符号:
-
a = 1当且仅当用了内联样式,否则为0 -
b= ID 选择器个数(#user、#modal各算 1,#app #main就是b=2) -
c= 所有类名(.btn)、属性([type])、伪类(:hover、:not(.active)中括号内部分)的总数 -
d= 标签名(div、p)和伪元素(::before)个数,组合符(、>、+)不计
例如:article#main .post[data-id]:hover::after → (0,1,3,2)(1 个 ID + 1 类 + 1 属性 + 1 伪类 = c=3;article + ::after = d=2)
为什么加了 class 还盖不过 ID?常见误判场景
开发者常以为 “写得更具体 = 更优先”,但 CSS 不看“看起来多不多”,只看四位是否高位占优。以下都是真实踩坑点:
立即学习“前端免费学习笔记(深入)”;
- 写
.modal .content span((0,0,2,3))想覆盖#user-name((0,1,0,0))→ 失败,b=1 > b=0直接碾压 - 用
div#header((0,1,0,1))和#header((0,1,0,0))权重相同,后写的才生效——加标签反而没用 -
:not(.active)本身不加权,但里面那个.active算 1 个c,容易漏数 - 继承来的样式权重是
(0,0,0,0),哪怕父级是#app,子元素写一行p { color: red; }((0,0,0,1))立刻生效
真要覆盖 ID 选择器?别赌顺序,换策略
靠写在后面、加更多类、或者深层嵌套,都不可靠。真正稳的方式只有两种:
- 用更高位:改用内联样式(
style="color: red"),但破坏可维护性 - 升一位:把目标选择器本身带上 ID,比如从
#user-name改成#user-name.edit-mode((0,1,1,0)),再写规则时自然高于原 ID - 慎用
!important:它能破局,但会污染后续所有覆盖逻辑,且无法对抗用户样式表里的!important
最易被忽略的一点:权重和 DOM 结构深度、选择器“长度”、文件引入顺序都无关。只看你写了几个 ID、几个类、几个标签——盯住 (a,b,c,d),一位一位比,问题就清楚了。










