多个类或属性需同时排除时必须链式使用:not(),如button:not(.disabled):not(.skip),逻辑为“且”而非“或”,即元素须同时不满足所有条件;:not()内仅支持单个简单选择器,禁用复合选择器、伪元素及后代关系,且Safari≤15.4不支持多参数语法。

多个类或属性要同时排除,必须链式写 :not()
想让样式跳过带 .disabled 或 .skip 的元素?不能写成 :not(.disabled, .skip) —— Safari ≤15.4 会静默忽略整条规则,DevTools 里直接划掉那行 CSS。正确做法是把两个 :not() 并列拼在一起:button:not(.disabled):not(.skip)。
这不是“先排除 disabled、再从剩下里筛 skip”,而是“这个 button 必须既不带 .disabled,也不带 .skip”——逻辑是“且”,不是“或”。如果一个元素同时有这两个类,照样被排除。
- ✅ 正确:
input:not([type="hidden"]):not(:disabled) - ✅ 正确:
div:not(.a):not(.b):not([data-ignore])(三个条件都得不满足) - ❌ 错误:
div:not(.a, .b)(旧版 Safari 不认,整条规则失效) - ⚠️ 注意:链式超过三个
:not()时,可读性骤降,建议改用 JS 动态加统一类控制
:not() 里能写伪类,但不能写类型+伪类组合
你可以安全地在 :not() 里用 :hover、:disabled、:first-child 这类伪类,但不能把标签名和伪类捆在一起写,比如 input:checked 是复合选择器,放进 :not() 就非法。
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
- ✅ 合法:
a:not(:visited)、li:not(:nth-child(2n))、button:not(:disabled) - ❌ 非法:
input:not(input:checked)(类型 + 伪类 = 复合) - ❌ 非法:
p:not(.sidebar p)(含空格 = 后代选择器) - ⚠️ 重点:
:not()括号内只接受单个简单选择器,浏览器不报错,但整条规则会被丢弃
想排除“某容器下的子元素”?:not() 做不到,得换思路
:not() 只作用于当前元素自身,无法表达“不在某个父级下”这种上下文关系。比如想给所有 p 加边框,但跳过 .sidebar p —— 写 p:not(.sidebar p) 是错的,语法非法;写 p:not(.sidebar) 也没用,因为 p 本身不会带 .sidebar 类。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确做法:正向限定作用域,比如
.content p { border: 1px solid #ccc; },而不是靠:not()去“反向过滤” - ✅ 替代方案:用
:is()或:where()配合,如:is(section > p, article p):not(.ignore) - ⚠️ 记住:
:not()不是万能排除器,它不处理层级、不处理祖先,只看当前节点是否匹配括号里的那个简单条件
优先级和兼容性容易被低估
:not() 自身不增加特异性权重,但它内部的选择器权重会叠加到整个选择器上。比如 div:not(.foo) 的优先级是 div(0,0,1) + .foo(0,1,0) = (0,1,1),比单纯的 div 高。
- ✅ Chrome 100+ / Firefox 95+ 支持
:not(.a, .b)多参数写法,但 Safari 目前仍不支持 - ✅
:not([data-id])优先级只有(0,1,0),比:not(.class)(0,1,0)低不了多少,但比div:not(.class)(0,1,1)低 - ⚠️ 最容易被忽略的是:DOM 动态变化后,
:not()规则不会“重算”已应用的样式——比如 JS 后续加了.disabled类,浏览器会立刻重新匹配,但框架 scoped style 或 shadow DOM 里可能行为不同

















