:not()仅支持单个简单选择器,不支持逗号分隔或多层复合选择器;正确写法是嵌套如div:not(.a):not(.b),且不能用于父选择或伪元素,需注意兼容性与逻辑本质。

使用 :not() 时必须传入简单选择器
直接写 :not(.foo, .bar) 是无效的——CSS 规范只允许 :not() 接收一个「简单选择器」(如类名、属性选择器、伪类,但不能是逗号分隔的列表或复合选择器)。浏览器会直接忽略整个规则。
常见错误现象:div:not(.a, .b) { color: red; } 在所有浏览器中都不生效;开发者工具里该样式会被划掉,显示“Invalid CSS”。
正确做法是把逻辑拆开,用多次 :not() 嵌套或组合:
-
div:not(.a):not(.b)—— 同时排除两个类(推荐,语义清晰) -
div:not([data-ignore]):not(:hover)—— 混合属性和伪类也合法 - 避免
:not(div.class),因为div.class是复合选择器,不被支持
:not() 不能匹配祖先或兄弟元素
它只作用于当前选中的元素本身,无法“向上排除父级有某类的子元素”,也不能“排除后面紧邻某个元素的前一个”。这是初学者最容易误解的点。
例如,想选“父容器不是 .disabled 的按钮”,不能写 button:not(.disabled > button)——语法非法,且逻辑错位。
正确思路是换主体:
- 改用父选择器:写成
.container:not(.disabled) button - 或加一层 class:给符合条件的
button主动加.enabled,再用button.enabled - CSS 无原生“父选择器”,
:not()也无法补足这个缺口
与伪元素、动态状态结合的限制
:not() 可以包含其他伪类(如 :hover、:checked),但不能包含伪元素(::before、::after),因为伪元素不是“可选中的元素节点”。
典型错误:input:not(::placeholder) 无效;span:not(:nth-child(2)) 是合法的(:nth-child 是伪类)。
另外注意优先级和覆盖问题:
-
p:not(.intro) { font-size: 14px; }和p.intro { font-size: 16px; }会正常共存 - 但如果写了
p { font-size: 14px; } p:not(.intro) { font-size: 12px; },那所有非.intro的p会变小,而.intro保持 14px——别误以为:not()有“重置”效果
兼容性与现代替代方案
:not() 在 IE9+ 支持单个参数,在 IE9 中不支持多个 :not() 连写(如 :not(.a):not(.b) 要到 IE10+);Safari 5.1–6.0 对某些嵌套伪类支持不稳定。
如果需要兼容老版本或逻辑复杂,可考虑:
- 用 JS 动态增删 class,再用朴素类选择器控制样式
- CSS 新特性如
has()(div:not(:has(> .error)))目前仅 Chrome 105+ / Safari 15.4+ 支持,还不能当主力 - 构建时用 PostCSS 插件自动展开
:not(.a, .b)为:not(.a):not(.b),但需确认目标环境
真正麻烦的不是语法,而是习惯性把 :not() 当成“取反编程逻辑”来用——它只是过滤器,不是 if-else。写之前先问一句:我到底想让谁匹配,而不是谁不匹配。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











