:not()仅接受单个简单选择器,语法错误会导致整条CSS规则被浏览器静默丢弃;正确用法为链式如:not(.a):not(.b),它作用于当前元素自身,不支持嵌套、伪元素或组合器,且优先级等于内部选择器权重之和。

:not() 只接受单个简单选择器,写错就会整条规则被浏览器静默丢弃——不是“部分失效”,是压根不解析。
为什么 :not(.disabled) 有时完全没效果
常见错觉是它“漏匹配”,实际是语法非法导致规则被丢弃。浏览器 DevTools 里会直接划掉整行样式,显示“Invalid CSS”。只要括号里出现以下任一情况,就触发丢弃:
- 逗号分隔:
:not(.a, .b) - 空格或组合器:
:not(div.disabled)、:not(.parent .child) - 多类连写(虽属 Level 4 合法,但 Safari ≤15.4 静默忽略):
:not(.a.b) - 伪元素:
:not(::before)(伪元素不是可选中节点)
正确排除多个类必须链式写 :not(.a):not(.b)
想同时排除 .skip 和 .ignore,只能写成 div:not(.skip):not(.ignore)。这不是“或”逻辑,而是“且”:元素自身必须既不带 .skip,也不带 .ignore。
- 顺序无关:
:not(.a):not(.b)和:not(.b):not(.a)等价 - 如果元素同时有两者,照样被排除——符合预期
- 别幻想
:not(.a, .b),Chrome/Firefox/Safari 当前均未启用 Level 4 多参数语法 - 嵌套写法如
:not(:not(.active))是非法的,不要尝试
想排除“某容器下的子元素”?:not() 做不到
:not() 只作用于当前元素自身,无法向上查父级、也无法向下穿透子树。例如,想跳过 .sidebar 里的所有 p,不能写 p:not(.sidebar p)(语法错),也不能写 .sidebar p:not(*)(无意义)。
立即学习“前端免费学习笔记(深入)”;
- 可行做法是正向限定作用域:
main p、article p,避开.sidebar - 或用层叠覆盖:
p { background: #f0f0f0; }+.sidebar p { background: transparent; } -
:not(.sidebar) p看似可行,但前提是这些p的**直接父级**本身不是.sidebar——否则不匹配 - 实验性方案如
@layer或scope兼容性差,生产环境慎用
真正难的不是怎么写,而是该不该用
:not() 的优先级等于其内部选择器权重之和,比如 input:not([type="text"]) 特异性是 (0,0,2,1),和 input[type="text"] 同级。它不降权、不兜底、不响应 DOM 属性的异步变更(如 JS 动态设 el.disabled = true 后旧引擎可能不重绘)。
- 当排除逻辑变复杂(比如要排除“同时有 A 和 B”的元素),加一个语义类如
.is-excluded比硬凑:not()更稳 - 调试时优先看 DevTools 里哪条规则被划掉,而不是只看元素是否高亮
- 最常被忽略的一点:
:not()不是“样式开关”,它是“选择器过滤器”——选不中,就彻底没机会应用样式



















