:not(.classname) 仅排除匹配该类的选择器,而非所有带class属性的元素;要选无class属性的元素须用 :not([class]),二者语义严格不同且不可互换。

用 :not(.classname) 选中不含某类的同级元素
直接写 :not(.active) 就能选中所有不带 .active 类的同级元素,但它不是“只选没 class 属性的”,而是“只要没这个类就入选”。比如:<div>、<code><div class="btn"> 都会被选中,只有 <code><div class="btn active"> 被排除。
<p>常见错误是以为它能筛掉所有带 class 的元素——其实不能。它只做一次逻辑否定:是否匹配括号里的选择器?不匹配,就通过。</p>
<ul>
<li>✅ 正确场景:兄弟列表里想高亮所有“非禁用项”,用 <code>button:not(.disabled)
div:not(.sidebar) 会跳过 <div class="sidebar extra"> ——它不会,因为该元素仍匹配 <code>.sidebar
div:not(.sidebar) + p 是合法的,但 div:not(.sidebar) p 是后代关系,和同级无关要排除多个已知 class,得链式写 :not(.a):not(.b):not(.c)
CSS 不支持 :not(.a, .b) 这种逗号分隔写法,浏览器会直接丢弃整条规则。必须把每个类单独包进 :not() 并连写。
- ✅ 有效:
li:not(.loading):not(.error):not(.hidden) - ❌ 无效:
li:not(.loading, .error, .hidden)(语法错误,整条规则失效) - ? 提示:如果类名来自框架(如 React 的哈希类),这条路基本走不通,得换 JS 判断
真要选“完全没写 class 属性”的元素,用 :not([class])
:not([class]) 匹配的是 HTML 标签上**根本没出现 class= 属性**的元素。哪怕写成 class="" 或 class=" ",都算有该属性,不会被选中。
- ✅ 匹配:
<p>纯文本</p> - ❌ 不匹配:
<p class=""></p>、<p class=" "></p>、<p class="text"></p> - ⚠️ 别写成
[class=""]:那只会匹配空字符串值,漏掉class=" "这类带空格的情况
配合兄弟选择器时,过滤逻辑容易错位
比如想选 .trigger 后面第一个没 .highlight 的 p,写成 .trigger + p:not(.highlight) 是对的;但若写成 .trigger:not(.highlight) + p,实际是在判断 .trigger 自己有没有 .highlight,和后面的 p 无关。
- ✅ 推荐把类判断放在目标元素上,比如
section > p:not(.archived) - ❌ 避免把
:not()放在锚点位置,除非你真想限制那个锚点本身的条件 - ?
~和+本身不关心 class,它们只管 DOM 结构;class 过滤必须显式加在目标选择器上
:not(.x),后者必须用 :not([class]),二者语义完全不同,且无法互相替代。











