:not() 伪类
排除特定元素,实现反向选择
什么是 :not() 伪类?
:not() 伪类允许你选择不匹配特定选择器的元素。
它是一个强大的排除工具,可以帮助你精确地选择需要的元素,而无需为每个元素添加额外的类名。
在现代 CSS 中,:not() 已经支持复杂选择器列表,可以同时排除多个条件, 甚至可以链式使用多个
:not() 来实现更复杂的排除逻辑。
- 反向选择 - 选择不符合条件的元素
- 减少类名 - 避免为排除的元素添加额外类
- 支持复杂选择器 - 可以排除复杂的选择器组合
- 可链式使用 - 多个 :not() 可以组合使用
基础语法
:not() 接受一个或多个选择器作为参数,匹配不符合这些选择器的元素。
/* 基础语法 - 排除单个选择器 */
:not(selector) {
/* 样式规则 */
}
/* 排除多个选择器(现代语法) */
:not(selector1, selector2, selector3) {
/* 匹配"不是 selector1、selector2 或 selector3"的元素 */
/* 等价于:既不是 selector1,也不是 selector2,也不是 selector3 */
}
/* 常见用法示例 */
/* 选择除最后一个外的所有 li */
li:not(:last-child) {
border-bottom: 1px solid #ccc;
}
/* 选择没有 .active 类的链接 */
a:not(.active) {
color: gray;
}
/* 选择不是 disabled 的按钮 */
button:not(:disabled) {
cursor: pointer;
}
/* 排除多个类 */
div:not(.header, .footer, .sidebar) {
padding: 20px;
}
/* 链式使用 :not() */
input:not([type="submit"]):not([type="button"]) {
border: 1px solid #ccc;
}
现代浏览器支持在 :not() 中使用复杂选择器列表。 你可以在一个
:not() 中排除多个选择器,而不需要链式使用多个 :not()。
/* 旧语法 - 链式使用(兼容性更好) */
p:not(.intro):not(.summary) { }
/* 新语法 - 一次排除多个(更简洁) */
p:not(.intro, .summary) { }
/* 两者完全等价!都表示"既不是 .intro 也不是 .summary" */
逻辑解释::not(.intro, .summary) 表示"不是(.intro 或 .summary)",
根据德摩根定律,等价于"不是.intro 且 不是.summary"
:not() 本身不增加优先级,但其参数中的选择器会计入优先级。 与 :is() 类似,:not()
的优先级取决于其参数列表中优先级最高的选择器。
/* :not() 的权重取决于参数 */
:not(.class) { } /* 权重: (0,1,0) */
:not(#id) { } /* 权重: (1,0,0) */
:not(div) { } /* 权重: (0,0,1) */
:not(.a, .b, #id) { } /* 权重: (1,0,0) - 取最高 */
基础排除示例
:not(A, B, C) 表示"不是(A 或 B 或 C)",根据德摩根定律,等价于"不是A 且 不是B 且 不是C"
示例:p:not(.intro, .summary) 只会选中既没有
.intro 类也没有 .summary 类的 <p> 元素
示例 1: 选择除最后一个外的所有元素
- 列表项 1 - 有底部边框
- 列表项 2 - 有底部边框
- 列表项 3 - 有底部边框
- 列表项 4 - 有底部边框
- 列表项 5 - 最后一个,没有边框
💡 除了最后一个列表项,其他都有底部边框和间距
/* 为除最后一个外的所有 li 添加边框 */
li:not(:last-child) {
border-bottom: 2px solid green;
margin-bottom: 10px;
}
/* 这样可以避免最后一个元素有多余的边框
比手动为每个元素添加类名更简洁 */
示例 2: 排除特定类的元素
💡 普通盒子使用蓝色样式,特殊盒子使用黄色样式
/* 为所有不是 .special 的盒子设置蓝色样式 */
.box:not(.special) {
background: lightblue;
color: darkblue;
border-color: blue;
}
/* 特殊盒子单独设置样式 */
.box.special {
background: lightyellow;
color: darkorange;
border-color: orange;
}
/* 优势:不需要为每个普通盒子添加额外的类名 */
示例 3: 排除多个条件
💡 排除了 primary、danger、warning 类的按钮都使用默认样式
/* 为所有不是特殊类型的按钮设置默认样式 */
button:not(.primary, .danger, .warning) {
background: #f5f5f5;
color: #333;
border-color: #ccc;
}
button:not(.primary, .danger, .warning):hover {
background: white;
border-color: #999;
}
/* 特殊按钮单独设置样式 */
button.primary { background: green; color: white; }
button.danger { background: red; color: white; }
button.warning { background: orange; color: white; }
/* 一次排除多个条件,比链式 :not() 更简洁 */
链式 :not() 示例
多个 :not() 可以链式使用,实现更复杂的排除逻辑。每个 :not() 都会进一步过滤元素。
示例 1: 多个 :not() 组合使用
💡 链式 :not() 排除了 demo-header、demo-footer、demo-sidebar,只有主内容区域显示绿色
/* 链式使用多个 :not() */
.item:not(.demo-header):not(.demo-footer):not(.demo-sidebar) {
background: lightgreen;
color: darkgreen;
border-color: green;
}
/* 等价于现代语法(如果浏览器支持) */
.item:not(.demo-header, .demo-footer, .demo-sidebar) {
background: lightgreen;
color: darkgreen;
border-color: green;
}
/* 每个 :not() 都会进一步过滤元素
只有同时不是 demo-header、demo-footer、demo-sidebar 的元素才会被选中 */
示例 2: 复杂条件排除
普通优先级
高优先级
普通优先级
(灰色)
高优先级
低优先级
(灰色)
普通优先级
💡 既不是激活状态也不是高优先级的卡片显示为灰色
/* 排除激活状态和高优先级的卡片 */
.card:not([data-status="active"]):not([data-priority="high"]) {
background: #f5f5f5;
color: #999;
opacity: 0.6;
}
/* 激活状态的卡片 */
.card[data-status="active"] {
background: lightgreen;
color: darkgreen;
}
/* 高优先级的卡片 */
.card[data-priority="high"] {
background: lightcoral;
color: darkred;
}
/* 同时满足两个条件的卡片 */
.card[data-status="active"][data-priority="high"] {
background: lightyellow;
color: darkorange;
}
/* 链式 :not() 实现"既不是...也不是..."的逻辑 */
示例 3: 结合其他伪类使用
- 第一项 - 蓝色(不可悬停)
- 中间项 1 - 可悬停变绿
- 中间项 2 - 可悬停变绿
- 中间项 3 - 可悬停变绿
- 中间项 4 - 可悬停变绿
- 最后一项 - 粉色(不可悬停)
💡 只有中间的列表项在悬停时会变色和移动
/* 只为中间的列表项添加悬停效果 */
li:not(:first-child):not(:last-child):hover {
background: green;
color: white;
transform: translateX(10px);
}
/* 第一项和最后一项有特殊样式 */
li:first-child {
background: lightblue;
color: darkblue;
}
li:last-child {
background: lightpink;
color: darkred;
}
/* 链式 :not() 结合伪类,实现精确控制 */
表单验证场景
:not() 在表单验证中非常有用,可以轻松选择未填写、未禁用或特定状态的表单元素。
场景 1: 排除已填写的输入框
💡 已填写的输入框显示绿色边框,未填写的显示黄色边框
/* 已填写的输入框(不显示占位符) */
input:not(:placeholder-shown) {
border-color: green;
background: lightgreen;
}
/* 未填写的输入框(显示占位符) */
input:placeholder-shown {
border-color: orange;
}
/* :placeholder-shown 伪类在输入框为空时匹配
:not(:placeholder-shown) 选择已有内容的输入框 */
场景 2: 排除禁用的按钮
💡 只有未禁用的按钮可以悬停和点击
/* 只为未禁用的按钮设置交互样式 */
button:not(:disabled) {
background: green;
color: white;
cursor: pointer;
}
button:not(:disabled):hover {
background: darkgreen;
transform: translateY(-2px);
}
/* 禁用的按钮 */
button:disabled {
background: #f5f5f5;
color: #999;
cursor: not-allowed;
opacity: 0.5;
}
/* 避免为禁用按钮添加不必要的交互效果 */
场景 3: 必填字段验证
💡 必填字段有效时显示绿色,无效时显示红色;可选字段使用虚线边框
/* 必填字段:已填写且有效 */
input:required:not(:focus):not(:placeholder-shown):valid {
border-color: green;
background: lightgreen;
}
/* 必填字段:已填写但无效 */
input:required:not(:focus):not(:placeholder-shown):invalid {
border-color: red;
background: lightcoral;
}
/* 可选字段:使用虚线边框 */
input:not(:required) {
border-style: dashed;
}
/* 多个 :not() 组合:
- 不在焦点状态
- 不显示占位符(已填写)
- 配合 :valid/:invalid 实现实时验证 */
浏览器兼容性
:not() 伪类是 CSS 的基础特性,在所有现代浏览器中都得到了支持:
| 浏览器 | 基础支持 | 复杂选择器列表 | 状态 |
|---|---|---|---|
| Chrome / Edge | 1+ | 88+ | ✓ |
| Firefox | 1+ | 84+ | ✓ |
| Safari | 3.1+ | 9+ | ✓ |
| Opera | 9.5+ | 74+ | ✓ |
基础 :not() - 只支持简单选择器,所有浏览器都支持
复杂选择器列表 - 支持 :not(selector1, selector2) 语法,需要较新版本
如果需要支持旧版浏览器,可以使用链式 :not() 代替复杂选择器列表:
/* 旧浏览器兼容写法 */
element:not(.a):not(.b):not(.c) { }
/* 现代浏览器简化写法 */
element:not(.a, .b, .c) { }