:not()因括号内含非法内容(如空格、多类连写、逗号分隔等)会被浏览器直接忽略,仅支持简单选择器;排除多个类需链式写:not(.a):not(.b);:not()只作用于元素自身,不涉及祖先或属性存在性判断。

为什么 :not(.foo) 有时完全没效果
不是选择器没匹配上,而是浏览器压根没解析这条规则——因为括号里写了非法内容。CSS 规范只允许 :not() 接收「简单选择器」,任何含空格、点号连写多个类(如 .a.b)、标签+类组合(如 div.active)、后代选择器(如 .header .nav)都会导致整条 CSS 规则被丢弃,样式彻底不生效。
常见错误写法:
-
:not(.disabled.hidden)❌ 多类名连写在 Level 3 中不被普遍支持(虽语法上算一个简单选择器,但 Safari 15.4 及更早版本会静默忽略) -
:not(div.active)❌ 含空格 → 被识别为非法后代选择器 -
:not(.a, .b)❌ 逗号分隔多条件 → 语法错误,整条规则作废
真正安全的只有::not(.class)、:not([attr])、:not(button)、:not(:hover)(注意 Chrome 105+ 才支持后者)。
:not() 怎么正确排除多个类
必须链式叠加,逻辑是 AND(且关系),不是 OR。想表达“既不是 .skip,也不是 .ignore”,就得写成:
div:not(.skip):not(.ignore) { opacity: 1; }
这表示:目标元素自身同时不带 .skip 类 且 不带 .ignore 类。
关键点:
- 顺序无关,
:not(.a):not(.b)和:not(.b):not(.a)等价 - 如果某个
div同时有.skip和.ignore,它依然不会被选中——这是符合预期的 - 不要写
div:not(.skip, .ignore),现代浏览器仍不支持该语法(Level 4 规范虽已定义,但 Chrome/Firefox/Safari 均未全量启用)
想排除「无 class 属性」的元素怎么办
:not(.foo) 匹配的是“不含 .foo 类”的元素,哪怕它有其他类(比如 class="bar baz")也会命中。真要限定“连 class 属性都没写”,得换思路:
-
p:not([class])→ 只匹配<p>文本</p>,不匹配<p class=""></p>或<p class="x"></p> -
button:not([disabled]):not([readonly])→ 排除属性存在的元素,和 JS 动态设置的disabled = false无关 -
input:not(:disabled):not(:read-only)→ 判断运行时真实状态,更贴近用户交互反馈
:not() 无法解决祖先限制问题
.vp-doc p:not(.vp-raw) 这种写法,只会排除那些 p 元素自己带 .vp-raw 类的情况,对 .vp-raw 内部嵌套的 p 完全无效。因为 :not() 只看目标元素自身,不查它的父辈。
错误期待:.vp-doc p:not(.vp-raw) 能阻止 .vp-raw 下所有 p 被样式影响 → 实际做不到。
可行方案:
-
.vp-raw * { all: revert; }—— 让整个子树回退到继承值或 UA 默认值(注意:all: revert不是清空样式,而是撤销作者样式层) - 用显式类控制作用域,比如统一加
.styled,而非靠否定逻辑兜底
真正容易被忽略的是::not() 的语义不是“排除某类”,而是“选中不匹配该条件的元素”。这个逻辑翻转一旦理解偏差,就会写出看似合理实则完全不执行的 CSS;而且它不提供“撤销”能力——CSS 里没有撤销,只有重新声明。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











