:not() 可替代冗余并列选择器,提升可维护性与兼容性;链式写法更可靠,避免非法语法和性能陷阱;适用前提为例外稳定、数量少、边界清晰。

用 :not() 替代多个并列选择器
当你要给「除某几类外的所有同类元素」加样式时,:not() 能直接替代一长串逗号分隔的选择器。比如想给所有标题设统一 margin,但跳过 h1 和 h2:
❌ 错误写法(冗余且易漏):h3, h4, h5, h6 { margin-top: 1rem; }
✅ 更稳的写法::is(h1, h2, h3, h4, h5, h6):not(:is(h1, h2)) { margin-top: 1rem; }
这里 :is() 先收拢所有标题标签,:not(:is(h1, h2)) 再一次性排除——逻辑清晰,增删标题类型时只需改 :is() 里的列表,不用反复调整并列项。
:not() 链式写法比多条件组合更可靠
想排除多个类、属性或状态?别堆 .a.b.c 这种连写,它在 Safari ≤15.4 里会被静默忽略;也别幻想 :not(.a, .b) 在旧环境可用——目前只有较新 Chrome/Firefox 支持 Level 4 多参数语法,Safari 仍不全支持。
-
div:not(.skip):not(.hidden):not([data-no-style])—— 安全、兼容、语义明确 -
input:not([type="hidden"]):not(:disabled):not([readonly])—— 按实际 DOM 状态筛选,比[readonly]属性更准(JS 动态设el.readOnly = true不会触发属性变化) - 顺序无关,但建议把高区分度条件放前面(如先筛
[type],再筛伪类),方便人眼快速判断意图
避免用 :not() 模拟「容器内排除」逻辑
常见误区是写 p:not(.sidebar p) 或 button:not(.modal .confirm),这类含空格或关系符的选择器是非法语法,整条 CSS 规则会被浏览器静默丢弃——DevTools 里直接划掉,不报错也不生效。
真正要跳过某个区域内的元素,得换思路:
- 正向限定作用域:
main p, article p { background: #f0f0f0; } - 层叠覆盖:
p { background: #f0f0f0; } .sidebar p { background: transparent; } - 用
:not(.sidebar) p仅在确保这些p的**直接父级不是.sidebar** 时才有效(比如<section><p></p></section>,而.sidebar是 section 的兄弟而非父级)
性能和可读性陷阱:否定逻辑不等于语义明确
:not() 是选择器过滤器,不是样式开关。它不降低优先级,也不兜底回退——选不中,就彻底没机会应用样式。
- 写
button:not(.ghost)看似省事,但后续加.outline类时,它也会被命中;而button.default语义清晰、可维护性强 - 浏览器匹配
li:not(.nav-item)时,需对每个li执行一次否定判断,DOM 节点多时可能拖慢渲染 - 调试时别只看元素是否高亮,重点查 DevTools 中该规则是否被划掉(语法错误)或被更高权重要素覆盖(层叠问题)
最常被忽略的一点::not() 的适用前提,是「例外稳定、数量少、边界清晰」。一旦排除条件开始滚动更新,就该收手,转用显式类名或结构化命名(如 BEM)来承载语义。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











