结论::not()括号内只能写一个简单选择器,否则整条规则被浏览器静默丢弃;正确写法是链式如p:not(.skip):not(.ignore),且仅作用于元素自身,不涉及祖先或后代。

直接说结论:用 :not() 排除样式时,括号里只能写一个「简单选择器」,写错就整条规则被浏览器静默丢弃——不是没效果,是压根不解析。
为什么 :not(.disabled) 有时完全不生效
不是元素没匹配上,而是浏览器 DevTools 里那行 CSS 被划掉了,显示 “Invalid CSS”。常见非法写法包括:
-
:not(.a.b)(多类名在旧版 Safari ≤15.4 中被忽略) -
:not(div.btn)(标签+类组合,非 Level 4 标准) -
:not(.parent .child)(含空格,后代选择器,语法错误) -
:not(.a, .b)(逗号分隔在部分环境未启用,IE 完全不支持)
只要括号内出现上述任一情况,整条规则失效,且无报错提示。调试时第一反应不该是“逻辑错了”,而是打开 DevTools 看这行是否被划掉。
:not() 怎么写多个排除条件才可靠
想同时排除 .skip 和 .ignore,必须链式写:p:not(.skip):not(.ignore)。这不是“或”逻辑,而是“且”——元素必须既不带 .skip,也不带 .ignore 才会被选中。
- 顺序无关:
:not(.a):not(.b)和:not(.b):not(.a)等价 - 别写
:not(.a, .b)—— 虽然 CSS Level 4 允许,但 Safari ≤15.4、旧版 Android WebView 会静默忽略 - 如果某
p同时有两者,它照样被排除,符合预期
真正容易踩的坑是误以为链式 :not() 是“排除任意一个”,结果发现加了新类后样式意外透出。
想排除“某容器下的子元素”,:not() 做不到
:not() 只看目标元素自身,不查祖先、不穿透后代。例如,.vp-doc p:not(.vp-raw) 只排除那些 p 自身带 .vp-raw 类的情况,对 .vp-raw 内部嵌套的 p 完全无效。
- 错误期待:
p:not(.sidebar p)(语法错)或:not(.sidebar) p(只匹配父级不是.sidebar的p,但无法保证层级关系) - 可行方案:
.sidebar p { all: revert; }(把子树样式交还给继承链和 UA 默认值) - 更稳做法:正向限定作用域,比如只给
main p、article p写样式
这时候用层叠覆盖比硬凑 :not() 更直观、更可控。
:not() 的优先级和性能容易被低估
:not() 本身不增加权重,但括号内选择器的权重会累加。比如 input:not([type="text"]) 特异性是 (0,0,2,1),和 input[type="text"] 同级——你以为在排除,实际可能压过了其他规则。
- 写
form :not(.hidden) input不如写form input:not(.hidden),后者结构更清晰、权重更易预判 - 大量节点下,
ul > li:not(.special)比ul > li多一次否定判断,渲染开销略高 - 可读性陷阱:写
button:not(.ghost):not(.outline)不如定义一个语义类.default-btn,后续加新类型时不易漏
真正难的不是语法怎么写,而是判断这个排除逻辑该交给 :not() 还是交给层叠——前者简洁,后者容错更高;一旦 DOM 动态增删类,:not() 不会自动重匹配旧引擎(如某些安卓 WebView),这点常被忽略。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











