CSS权重是四位独立整数(a,b,c,d)逐位比较,不加法、不进位;a为内联样式个数,b为ID个数,c为类/属性/伪类个数,d为标签/伪元素个数;:not()内选择器计权,:is()取最高分支权重,:where()恒为(0,0,0,0),!important不改权重只改应用顺序。

权重不是加法,是 (a,b,c,d) 四位数逐位比较
很多人一看到 #header .nav li 就下意识算成 100 + 10 + 1 = 111,再跟另一个“111”比大小——这完全错了。CSS 权重本质是四位独立整数 (a,b,c,d),不进位、不相加、不换算,只从左到右一位一位比。
比如:#main .item:hover 是 (0,1,2,0),div#content p.text::before 是 (0,1,1,2)。b 都是 1,继续比 c:2 > 1,前者胜出——哪怕后者多一个标签和一个伪元素,d 再大也无效。
-
a:内联样式个数(仅style="..."算,值为 0 或 1) -
b:ID 选择器个数(#id,每个 +1) -
c:类 / 属性 / 伪类个数(.cls、[type]、:hover等,每个 +1) -
d:标签 / 伪元素个数(div、::before,每个 +1)
:not() 里的选择器才计权,:not 本身不算
这是最容易漏算的点。:not(.disabled) 整体不增加 c 值,但括号里的 .disabled 会正常计入 c 位。也就是说,它和单独写 .disabled 在权重上完全等价。
对比这两个选择器:
立即学习“前端免费学习笔记(深入)”;
-
button:not(.primary)→(0,0,1,1)(括号内 1 个类,外面 1 个标签) -
button.primary→(0,0,1,1)(同样 1 个类 + 1 个标签)
再复杂点:form :not([type="submit"]) input → (0,0,1,3):括号内 [type="submit"] 贡献 1 个 c,form 和 input 各贡献 1 个 d,中间空格不计权。
::is() 和 :where() 的权重行为完全不同
::is() 和 :where() 看起来相似,但权重处理截然相反:
-
:is(.a, #b)按其中**最高权重分支**计算,即按#b的(0,1,0,0)算 -
:where(.a, #b)恒为(0,0,0,0),强制降权,无视内部任何高权重选择器
这意味着 :where(#header .nav) 的优先级和 * 一样低,适合做“安全覆盖”;而 :is() 可能意外拉高权重,调试时要特别注意 DevTools 里显示的实际 specificity 值。
!important 不改变权重,只改应用顺序
!important 不是“把权重调成 9999”,它绕过整个权重系统,属于独立裁决层。只要声明带 !important,就先于所有不带它的规则处理;但如果多个都带,则仍要回退到 (a,b,c,d) 比较。
例如:
-
.box { color: blue !important; }vs#app .box { color: red; }→ 前者生效(有!important,后者没有) -
.box { color: blue !important; }vs#app .box { color: red !important; }→ 后者生效,因为(0,1,1,0) > (0,0,1,0)
另外,style="color:green !important" 是合法的,且优先级高于任何外部 !important 声明——这点常被忽略,DevTools 里看到带删除线的样式,往往就是被这种内联 !important 覆盖了。


















