直接查看Chrome DevTools Styles面板中悬停选择器显示的specificity四元组(如0,1,0,1),按inline-ID-class-tag逐位比较,比口诀更准,可精准判断伪类选择器优先级。

怎么一眼看出哪个伪类选择器赢了
别靠猜,直接打开 Chrome DevTools → 选中元素 → 切到 Styles 面板,鼠标悬停在任意 CSS 规则的选择器上,浏览器会显示类似 0,1,0,1 的 specificity 值(格式为 inline-ID-class-tag)。这个四元组比“ID > 类 > 标签”的口诀更准,尤其当出现 :not()、:hover 和属性选择器混用时。
常见误判点:
-
.btn:hover是0,1,1(1 个类 + 1 个伪类),不是 “类比 hover 高” -
div[role="button"]:focus是0,2,1(1 个类?不,这里没类;是 1 个属性选择器 + 1 个伪类 + 1 个标签 →0,0,2,1) -
:not(.disabled):hover的:not()本身不加分,但括号里.disabled算 1 个类 → 整体是0,1,1
为什么 .menu a:hover 总是压不过 .nav-link.active
表面看都是“类 + 伪类”,但权重可能差一截。比如:
-
.menu a:hover→ 2 个类?不,.menu是类(+10),a是标签(+1),:hover是伪类(+10)→0,0,2,1 -
.nav-link.active→ 两个类 →0,0,2,0
这时两者 class 数相同,但前者多一个标签位(d=1),所以 .menu a:hover 实际更高 —— 这就是你改了 .active 颜色却没生效的原因。
立即学习“前端免费学习笔记(深入)”;
修复建议:
- 把悬停样式也收进单个语义类,比如
.nav-link--hoverable:hover,保持结构扁平 - 避免用后代选择器绑定交互态,
.nav-link:hover比.nav .list a:hover更可控 - 检查是否意外引入了 ID 或属性选择器(如
[data-testid="nav-link"]),它们会让权重跳升
SCSS 里 &:hover 编译后权重暴增怎么办
& 不是“只拼类名”,而是完整展开父级路径。例如:
.dashboard-layout .sidebar .nav { &:hover { color: blue; } }
编译结果是 .dashboard-layout .sidebar .nav:hover,权重为 0,0,0,3(三个标签 + 一个伪类),远超你本意的 .nav:hover(0,0,1,0)。
真正安全的做法:
- 伪类声明尽量提至顶层,和基础类平级:
.nav:hover { }而非嵌套在布局容器里 - 需要复用?定义工具类:
.u-interactive:hover { cursor: pointer; },再叠加使用 - 禁用
&:not(...)嵌套写法,:not()内部的选择器也会被计分,容易触发非法语法或隐性升权
哪些伪类操作会悄悄锁死后续覆盖
有些写法看似合理,实则让后续样式几乎无法调整:
-
#header .title:hover:ID 已占 100 分,后面加啥都难反超 -
button:is(:hover, :focus, :active)::is()不影响权重,但括号内每个选择器都参与计算,实际等价于分别写三条规则,体积大且调试难 -
input[type="text"]:not([disabled]):required:focus:4 个可计分项(1 标签 + 1 属性 + 1 伪类 + 1 属性 + 1 伪类?错 ——[disabled]在:not()里,只算 1 次;:required是伪类;:focus是伪类;input是标签 →0,0,3,1)
最常被忽略的一点:JS 动态设置的 element.style.color 天然带 a=1,权重高于所有外部 CSS。如果发现样式“怎么调都不变”,先检查 computed styles 里有没有 inline style 被激活。


















