:not([attr])用于选中不带某属性的元素,如div:not([data-id]);注意其仅支持简单选择器,且[attr]与[attr=""]语义不同,前者判断属性存在性,后者匹配空值。

用 :not([attr]) 选中“不带某属性”的元素
直接写 [attr] 是找“有属性”,反过来要找“没有”,就得靠否定伪类 :not() 包一层。比如想给所有没写 data-id 的 div 加灰边,就得写 div:not([data-id]),而不是幻想存在一个 [data-id="undefined"] 这种东西。
注意::not() 里只能放简单选择器(不能嵌套另一个 :not,也不能写后代关系),所以 :not(div [data-id]) 是非法的;但 div:not([data-id])、input:not([required]) 都完全合法。
:not([attr]) 和 :not([attr=""]) 完全是两回事
初学者常把“没这个属性”和“这个属性值为空字符串”混为一谈。比如:
-
button:not([disabled])→ 排除所有显式写了disabled的按钮(包括<button disabled></button>、<button disabled></button>) -
button:not([disabled=""])→ 只排除那些明确写了disabled=""的按钮,而<button disabled></button>反而会被选中(因为它的属性值是undefined,不是空字符串)
绝大多数场景下你要的是前者——判断属性“是否存在”,而不是抠它内部存了什么字符串。
哪些地方容易静默失效?
几个实操中高频翻车点:
- 属性名大小写写错:
div:not([Data-ID])在 HTML 中不会匹配data-id,CSS 属性选择器区分大小写 - 引号漏掉或错用:
div:not([data-role=header])看似省事,但一旦值含空格或连字符(如data-role="main nav"),就会解析失败;应统一写成[data-role="header"] - 误以为能匹配 JS 动态移除的属性:如果 JS 执行了
el.removeAttribute('data-loaded'),:not([data-loaded])才会生效;但若只是el.dataset.loaded = '',属性依然存在,选择器照样不触发
真要兼顾语义和可读性,别只依赖 :not([attr])
纯靠否定选择器容易让样式逻辑变绕,尤其当多个条件叠加时。比如 input:not([type="text"]):not([type="email"]):not([type="number"]) 已经很难一眼看懂意图。更稳妥的做法是:
- 对需要特殊处理的元素主动加 class,比如
class="no-validate",再写input.no-validate - 用
[type]先兜底,再用:not([type])处理无类型输入框,比堆砌多个:not清晰得多
否定选择器很实用,但它本质是“排除法”,不是“定义法”。越复杂的业务逻辑,越要警惕靠它撑起整套样式体系。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











