:not() 不提高自身优先级,但括号内选择器参与权重计算;如 div:not(.foo) 权重为 (0,1,1),高于 .foo 的 (0,1,0);降权应去除高权前缀或改用语义类,而非依赖 :where() 修复。

:not() 本身不提高优先级,但括号里的选择器会参与权重计算——所以“过高”不是它的问题,是你没意识到它悄悄加了分。
为什么 :not(.foo) 比 .foo 还难覆盖
因为 :not(.foo) 是独立选择器,不带外部上下文;而 div:not(.foo) 的权重是 div(d=1) + .foo(c=1),合计 (0,1,1),高于单独 .foo 的 (0,1,0)。浏览器比的是四元组,高位 c 相等时才看 d,但这里 c 已经赢了。
- 常见翻车:
input:not([type="hidden"])权重 =input(d=1) +[type="hidden"](c=1) = (0,1,1),远超input自身的 (0,0,1) - 别指望用
:where()包一层来降权::where(input:not([type="hidden"]))权重仍是 (0,0,0,0),直接被其他规则无视 - 多个
:not()不叠加权重:button:not(.primary):not(.danger)还是 (0,1,1),和button:hover同级
真正有效的降权方式:砍掉外部选择器
问题不在 :not(),而在你给它套了个高权前缀。目标是让整个选择器权重回归到 (0,1,0) 或更低。
- 把
section .card:not(.disabled)改成.card:not(.disabled)—— 去掉section这个无意义的父级限定 - 避免用标签名限定:
div:not(.hidden)→ 改为.not-hidden(新增语义类),权重恒为 (0,1,0) - 如果必须保留元素上下文,改用属性选择器替代:
[role="button"]:not([disabled]),比button:not([disabled])少一个 d 值
用 :where() 真正该用的地方
:where() 不是用来“修复” :not() 的,而是当你需要一组选择器统一让权时才启用——比如 reset 规则、第三方样式兜底。
立即学习“前端免费学习笔记(深入)”;
- 正确用法:
:where(.btn, .btn-primary, .btn--large) { padding: 0.5rem; },整条规则权重为 (0,0,0,0) - 错误用法:
:where(div:not(.hidden))—— 冗余且失效,:where()不改变匹配逻辑,只归零权重 - 必须配合加载顺序:
:where()规则得放在自定义样式表最前面,否则归零后反被后面高权规则压住 - Safari 15.4+ / Chrome 105+ 才稳定支持,老版本需 fallback,例如写成
.reset-btn类并显式重置
最容易被忽略的一点:权重不是十进制数,(0,1,1) ≠ 11,它是三段独立位;哪怕你写了十个 :not(),只要 a 和 b 位没变,就永远赢不了一个 #id。与其在 :not() 里绕弯子,不如检查 HTML 结构是否真需要那么长的选择器链。


















