css优先级本质是四元组(a,b,c,d)逐位比较,而非数值加总;a为内联样式数、b为id数、c为类/属性/伪类数、d为元素/伪元素数,从左到右高位优先,0-1-0-0(一个id)恒高于0-0-99-99(99个类+99个标签)。

CSS优先级不是“谁后写谁赢”,而是四位数逐位比较
很多人以为样式覆盖只看定义顺序,结果改了半天发现没生效——问题往往出在权重计算上。浏览器真正比的是 (a,b,c,d) 这个四元组:a 是内联样式的个数(style=""),b 是 ID 选择器个数,c 是类/属性/伪类个数,d 是标签/伪元素个数。比较时从左到右,高位相等才看下一位,0,1,0,0(一个 ID)永远大于 0,0,99,99(99 个类 + 99 个标签)。
常见错误:把权重当十进制数字加总
比如看到 #header .nav a:hover 就算成 100 + 10 + 1 + 10 = 121,这是错的。它实际是 (0,1,2,1):1 个 ID(b=1)、2 个 c 级(.nav 和 :hover)、1 个 d 级(a)。而 .container .sidebar .active 是 (0,0,3,0),哪怕数值“30”看起来比“121”小,但比较时是 0,0,3,0 vs 0,1,2,1 → b 位 0
-
:not()本身不贡献权重,但里面的内容会算(:not(.disabled)贡献 c=1) -
:is()和:where()权重取内部选择器的最高值,但:where()会归零(即不增加权重) - 通配符
*、组合符+/~、继承来的样式,权重全是(0,0,0,0)
Chrome DevTools 里怎么看真实权重?
打开开发者工具 → 选中元素 → 右侧“样式”面板。每条规则右侧有灰色小字显示来源,鼠标悬停能看到具体选择器;更关键的是切换到“计算”面板,找到某条属性(如 color),展开后能看到所有参与计算的规则,并标注哪条“已覆盖”、哪条“已应用”。这里显示的不是你写的原始选择器,而是浏览器内部解析后的有效权重路径。
- 如果某条本该生效的样式显示为“已覆盖”,点开它旁边的箭头,就能看到是哪条更高权重的规则压过了它
- 注意检查是否误用了
!important—— 它不参与(a,b,c,d)计算,而是直接置顶,但会破坏可维护性 - 内联样式(
style="...")哪怕只设一个color,也会让整条规则权重变成(1,0,0,0),轻松碾压几乎所有外部 CSS
排查时最容易被忽略的三个点
权重计算本身不难,但实操中常卡在这几个隐形环节:
- 伪类和伪元素混用:比如
a::before:hover是非法写法,浏览器会整个规则失效,而不是按预期计算权重 - ID 选择器带转义:
#my\#id中的\#是字面量 #,不算作 ID 选择器,实际权重可能比你以为的低 - CSS Modules 或 Vue scoped style 会自动加属性选择器(如
[data-v-abc123]),悄悄把 c 值 +1,导致和普通类名冲突时优先级变高
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











