:not() 是唯一直接表达“所有除了……”语义的 CSS 选择器,适用于同质元素中排除例外、表单状态过滤、导航分隔等场景,支持链式但不支持逗号分隔或多层嵌套否定,特异性由括号内选择器决定。

:not() 是唯一能直接表达“所有除了……”语义的 CSS 选择器。它不是万能筛子,但用对了,能省掉大量覆盖规则和冗余类名。
什么时候必须用 :not() 而不是写多个规则
当你面对一组同质元素(比如全是 button、全是 input、全是 li),又只想对其中“非例外”的部分统一设样式时,:not() 就是逻辑最干净的解法。
- 写
button:not(.primary) { margin-right: 8px; }比先写button { margin-right: 8px; }再用.primary { margin-right: 0; }覆盖更可靠——避免权重冲突和遗漏 - 处理表单时,
input:not([disabled]):not([readonly])可一次性排除两种不可交互状态,比分别加.enabled类更少侵入 HTML - 导航菜单中,
nav a:not(:last-child) { border-right: 1px solid #eee; }比给每个链接加class="has-divider"更易维护
:not() 支持哪些参数?哪些不能写
括号里只能填一个「简单选择器」,但这个“简单”比直觉宽泛——它允许类、ID、属性、伪类,甚至组合(如 [type="text"]:invalid),但不允许逗号分隔的多选器(除非你用的是支持 CSS Level 4 的现代浏览器)。
- ✅ 合法:
div:not(.skip)、a:not([href^="http"])、li:not(:first-child)、input:not(:disabled):not([type="hidden"]) - ❌ 非法:
div:not(.a, .b)(CSS3 不支持,会整个规则失效);p:not(em, strong)(语法错误);span:not(::before)(伪元素禁止) - ⚠️ 兼容提示:IE8 及更早版本完全不支持
:not();移动端和现代桌面浏览器均无问题
链式 :not() 和嵌套陷阱
想同时排除多个条件,不能写 div:not(.a, .b),但可以链式写 div:not(.a):not(.b)。这种写法在所有支持 :not() 的浏览器中都有效,且特异性清晰可算。
立即学习“前端免费学习笔记(深入)”;
- 链式写法等价于“且”关系:
input:not([required]):not(.no-validate)表示“既不要求必填、也不带 no-validate 类” - 不能嵌套否定:
:not(:not(.active))无效,浏览器会忽略整条规则 - 注意层级误判:
.container *:not(.exclude)会匹配.exclude内部的子元素(因为它们自己没这个类),真要排除整个子树得靠 JS 或重构结构
性能与特异性容易被忽略的点
:not() 本身不增加选择器权重,但它括号里的选择器会参与计算。这意味着 div:not(.foo) 的特异性是 (0,1,1),和 div.foo 相同,高于纯标签选择器 div(0,0,1)。
- 如果页面中已有高权重规则如
#nav ul li a,而你想用a:not(.external)覆盖它,大概率失败——得提高左边选择器权重或改用更具体的上下文 - 复杂
:not()不影响渲染性能,但过度嵌套(如:not(:not(:not(...))))会让调试变得困难,实际项目中应控制在两层以内 - 真正影响性能的是选择器匹配深度,而非
:not()本身;用ul > li:not(:last-child)比ul li:not(:last-child)更快,因为限制了查找范围


















