:not()是匹配不符合括号内条件的同级元素的结构伪类选择器,仅支持简单选择器,不能嵌套复合选择器或伪元素,其特异性不降低,常用于默认样式排除例外。

什么是 :not(),它真能“排除”元素?
:not() 是一个结构伪类选择器,作用是匹配**不符合括号内条件的所有同级元素**。它不是“隐藏”或“删除”,而是让 CSS 规则跳过被排除的元素——这点常被误解为“不生效”,其实是选择逻辑没覆盖到目标。
关键限制:括号里只能填**简单选择器**(如 .error、[disabled]、:checked),不能写复合选择器(如 div p)或伪元素(如 ::before)。Chrome 105+、Firefox 103+、Safari 15.4+ 支持完整语法;旧版 Safari 对属性选择器在 :not() 中的支持较弱。
:not() 常见错误写法与修正
这些写法会直接报错或失效:
-
li:not(.first, .last)→ 错误:逗号分隔多个选择器不被支持。应改写为li:not(.first):not(.last) -
button:not([type="submit"] [type="reset"])→ 错误:空格是后代选择器,:not()不接受。应写成button:not([type="submit"]):not([type="reset"]) -
input:not(:invalid:focus)→ 错误:伪类链式调用不合法。可拆为input:not(:invalid):not(:focus),但语义已变(排除的是既非 invalid 又非 focus 的元素) - 用
:not()模拟:has(),比如div:not(:has(p))→ 当前所有浏览器都不支持,:has()和:not()不能嵌套
真正实用的 :not() 场景
它最自然的用武之地是“默认样式 + 排除例外”,而不是强行构造复杂逻辑:
- 给所有按钮加统一边框,但去掉带
class="icon"的:button:not(.icon) { border: 1px solid #ccc; } - 表单中所有必填字段标红星,但跳过隐藏域:
input:not([type="hidden"]):required + label::after { content: " *"; color: red; } - 列表项默认有下划线,最后一项除外:
nav a:not(:last-child) { border-bottom: 1px solid #eee; }(注意这里:last-child是合法的,因为它是单一简单伪类) - 禁用状态下不触发 hover 效果:
button:not(:disabled):hover { opacity: 0.8; }
和 :is()、:where() 混用时的优先级陷阱
:not() 的权重跟它内部的选择器一致,但容易被忽略的是:它**不降低整体选择器特异性**。比如:
form input:not([type="hidden"]) { /* 特异性 = 0,1,1 */ }
而下面这行看似更“宽松”,其实特异性更高(因为 :is() 内部的 #id 拉高了整个选择器):
form :is(input, textarea):not(:is([type="hidden"], #ignore)) { /* 特异性 = 0,2,1 */ }
结果就是后者会覆盖前者,即使你本意是“补充规则”。实际项目中,除非明确需要叠加特异性,否则避免在 :not() 里混用 :is() 或 :where()。
真正难处理的,从来不是语法对不对,而是当你在多层嵌套、多人协作的 CSS 文件里看到 div:not(.skip):not([data-ignore]):not(:has(> .excluded)) 这种写法时——它已经失去了可读性,也失去了维护价值。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











