:not()仅支持简单选择器,如.cls、#id、[attr]、:hover;不支持后代、子代等复合选择器,否则整条规则被忽略。

伪类 :not() 只能接受简单选择器
很多人写 :not(.a .b) 或 :not(div p),浏览器直接忽略整条规则——因为 :not() 里面不支持后代、子代等复合选择器。它只认 .cls、#id、[attr]、:hover 这类单个、无空格、无连接符的“简单选择器”。
常见错误现象:button:not(.disabled):hover 能用,但 button:not(.btn-primary .active) 会静默失效。
- 可用:
:not(:disabled)、:not([data-hidden])、:not(.error) - 不可用:
:not(.container > .item)、:not(div + p)、:not(.a.b)(多类名连写是合法的,但注意这是“一个”简单选择器) - 想排除嵌套结构?得换思路:用更具体的选择器覆盖,或加 wrapper 类控制作用域
:not() 的优先级和层叠行为容易误判
写 input:not([type="checkbox"]) { width: 100%; },结果 checkbox 仍被设了 width?不是 :not() 失效,而是别的规则权重更高。:not() 本身不降低优先级,它括号里的选择器参与计算。
比如 input:not([type="text"]) 的优先级 = input(0,0,1,1) + [type="text"](0,0,1,0) = 0,0,2,1 —— 和 input[type="text"] 同级。
立即学习“前端免费学习笔记(深入)”;
- 别指望
:not()能“削弱”某条样式;它只是条件过滤,不影响权重 - 调试时用浏览器 DevTools 看“Styles”面板里哪条规则被划掉,而不是只看是否匹配
- 如果想让某些元素“回归默认”,显式写
width: auto比依赖:not()更可靠
动态属性变化时 :not() 不会触发重绘问题
:not([disabled]) 对 button 生效,但 JS 改了 el.disabled = true,样式却没变?不是 bug,是预期行为:布尔属性变更会触发属性变更,但部分老浏览器(如 IE)对 :not([disabled]) 响应不及时;现代浏览器没问题,但前提是属性确实被 DOM 正确反映。
使用场景:表单控件状态切换、Tab 面板激活态排除。
- 确保 JS 修改的是属性(
el.setAttribute('disabled', '')),而非仅改 property(el.disabled = true)——后者不触发 attribute 选择器匹配 - 更稳妥的做法:用 class 控制,比如
button:not(.is-disabled),JS 切 class,CSS 稳定响应 - React/Vue 等框架中,直接绑定
className或比依赖属性更可控</li> </ul> <H3>兼容性底线:IE9+ 和所有现代浏览器都支持,但写法有坑</H3> <p><code>:not()
在 IE9 就支持,但 IE9–IE11 不支持多个参数,比如:not(.a, .b)是非法语法,必须拆成两条规则。Chrome/Firefox/Safari 早已支持逗号分隔的多参数写法,但一写就掉兼容性。性能影响几乎可忽略,但嵌套过深的
:not()(比如div:not(:not(:not(.x))))可能增加解析负担,纯属自找麻烦。- 安全写法:
:not(.a):not(.b)(IE 兼容) - 简洁写法:
:not(.a, .b)(Chrome 57+/Firefox 52+/Safari 9.1+,但 IE 完全不认) - 别在关键路径上用
:not(:nth-child(2n))这类组合——:nth-child本身兼容性好,但嵌套进:not()后,IE 会整个丢弃该规则
真正难的不是语法,是判断什么时候该用
:not(),什么时候该用显式 class 或 JS 控制。样式越靠前声明、越少依赖运行时状态,越不容易翻车。 - 安全写法:










