CSS3 否定伪类选择器

CSS3 的 :not() 否定伪类选择器是一个功能强大的选择器,它允许我们选择不匹配特定选择器的元素。这个选择器为样式控制提供了极大的灵活性,特别是在需要排除某些元素或特殊情况时非常有用。

:not() 伪类概述

:not() 伪类选择器也称为否定伪类选择器,它接受一个选择器作为参数,选择所有不匹配该选择器的元素。这个选择器可以大大简化我们的 CSS 代码,避免编写冗长的选择器。

基本语法

:not(selector) {
  /* 样式规则 */
}

工作原理

:not() 选择器选择所有不匹配括号内选择器的元素。它可以接受任何有效的 CSS 选择器,包括元素选择器、类选择器、ID 选择器、属性选择器、伪类选择器等。

基本用法

排除特定类

/* 排除特定类 */
p:not(.intro) {
  text-indent: 2em;
}

/* 排除多个类 */
div:not(.no-padding):not(.no-margin) {
  padding: 20px;
  margin: 20px;
}

排除特定元素

/* 排除特定元素 */
li:not(.first) {
  margin-top: 10px;
}

/* 排除链接 */
a:not([href]) {
  color: #6c757d;
  cursor: default;
}

排除特定状态

/* 排除禁用状态 */
button:not(:disabled) {
  cursor: pointer;
}

/* 排除悬停状态 */
.nav-item:not(:hover) {
  opacity: 0.8;
}

高级用法

排除多个选择器

/* 排除多个类 */
div:not(.class1):not(.class2):not(.class3) {
  /* 样式 */
}

/* 排除多个元素 */
*:not(p):not(h1):not(h2) {
  font-size: 14px;
}

/* 排除多个属性 */
a:not([href^="http://"]):not([href^="https://"]) {
  color: #6c757d;
}

嵌套使用

/* 嵌套使用 */
.container > *:not(.header):not(.footer) {
  padding: 20px;
}

/* 复杂嵌套 */
.nav li:not(.active):not(:last-child) {
  margin-right: 10px;
}

结合其他选择器

/* 结合类选择器 */
.button:not(.disabled):not(.loading) {
  cursor: pointer;
}

/* 结合属性选择器 */
input:not([type="checkbox"]):not([type="radio"]) {
  width: 100%;
}

/* 结合伪类选择器 */
a:not(:visited):not(:hover) {
  color: #007bff;
}

实际应用场景

1. 排除特定样式的元素

/* 排除无边距的元素 */
.container > *:not(.no-margin) {
  margin-bottom: 20px;
}

/* 排除无内边距的元素 */
.card > *:not(.no-padding) {
  padding: 15px;
}

2. 表单样式

/* 表单输入框样式 */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]) {
  width: 100%;
  padding: 10px 15px;
  border: 1px solid #ced4da;
  border-radius: 4px;
}

/* 按钮样式 */
button:not(.disabled):not(.loading) {
  background: #007bff;
  color: white;
  border: none;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
}

button:not(.disabled):not(.loading):hover {
  background: #0056b3;
}

3. 列表样式

/* 列表项目样式 */
ul li:not(:first-child) {
  border-top: 1px solid #eee;
  padding-top: 10px;
}

ul li:not(:last-child) {
  margin-bottom: 10px;
  border-bottom: 1px solid #eee;
}

/* 排除特定类名的列表项 */
ul li:not(.separator) {
  padding: 10px 0;
}

4. 链接样式

/* 外部链接样式 */
a:not([href^="#"]):not([href^="javascript:"]) {
  color: #007bff;
  text-decoration: none;
}

a:not([href^="#"]):not([href^="javascript:"]):hover {
  text-decoration: underline;
}

/* 内部链接样式 */
a[href^="/"]:not(.external) {
  color: #28a745;
}

5. 网格布局

/* 网格项目样式 */
.grid > *:not(.full-width) {
  flex: 1;
  min-width: 200px;
}

.grid > *:not(.full-width):not(.featured) {
  background: #f8f9fa;
}

6. 导航菜单

/* 导航链接样式 */
.nav a:not(.active):not(.disabled) {
  color: #333;
  text-decoration: none;
}

.nav a:not(.active):not(.disabled):hover {
  color: #007bff;
}

/* 导航项目样式 */
.nav li:not(:first-child) {
  border-left: 1px solid #ddd;
}

.nav li:not(:last-child) {
  margin-right: 10px;
}

性能考虑

1. 避免过度使用

/* 不推荐 - 过度使用 */
*:not(.class1):not(.class2):not(.class3):not(.class4) {
  /* 样式 */
}

/* 推荐 - 使用类名 */
.element {
  /* 样式 */
}

2. 选择器优化

/* 推荐 - 更具体的选择器 */
.container > *:not(.excluded) {
  /* 样式 */
}

/* 不推荐 - 过于宽泛 */
*:not(.excluded) {
  /* 样式 */
}

3. 避免嵌套过深

/* 不推荐 - 嵌套过深 */
.container .sidebar .menu .item:not(.active) {
  /* 样式 */
}

/* 推荐 - 使用类名 */
.menu-item:not(.active) {
  /* 样式 */
}

:not() 的局限性

1. 不能嵌套使用

/* 不支持 */
:not(:not(.class))

/* 不支持 */
:not(:not(.class1):not(.class2))

2. 不能选择伪元素

/* 不支持 */
:not(::before)
:not(::after)

3. 不能选择伪类(特殊情况)

/* 不支持 */
:not(:hover)
:not(:focus)
:not(:active)

实际应用案例

1. 卡片网格排除

/* 卡片网格 */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 20px;
}

.card-grid > *:not(.full-width) {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.card-grid > *:not(.full-width):not(.featured) {
  padding: 20px;
}

.card-grid > *:not(.full-width):not(.featured):hover {
  transform: translateY(-5px);
  box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}

2. 表单验证排除

/* 表单验证 */
.form-control {
  width: 100%;
  padding: 12px 15px;
  border: 1px solid #ced4da;
  border-radius: 4px;
}

.form-control:not(:placeholder-shown):valid {
  border-color: #28a745;
}

.form-control:not(:placeholder-shown):invalid {
  border-color: #dc3545;
}

.form-control:not(:disabled):not(:read-only) {
  background: white;
}

3. 响应式布局排除

/* 响应式布局 */
.container {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.container > *:not(.full-width) {
  flex: 1;
  min-width: 250px;
}

@media (max-width: 768px) {
  .container > *:not(.full-width) {
    min-width: 100%;
  }
}

4. 文章排版排除

/* 文章排版 */
article p {
  line-height: 1.8;
  margin-bottom: 1.5em;
}

article p:not(.intro):not(.excerpt) {
  text-indent: 2em;
}

article p:not(.intro):not(.excerpt):first-of-type {
  text-indent: 0;
}

article img:not(.full-width) {
  max-width: 50%;
  float: left;
  margin: 0 20px 20px 0;
}

5. 按钮组排除

/* 按钮组 */
.button-group {
  display: flex;
  gap: 10px;
}

.button-group button:not(.primary):not(.secondary):not(.danger) {
  background: #f8f9fa;
  color: #333;
  border: 1px solid #dee2e6;
}

.button-group button:not(.primary):not(.secondary):not(.danger):not(:disabled):hover {
  background: #e9ecef;
}

浏览器兼容性

:not() 伪类选择器在所有现代浏览器中都有良好的支持:

  • Chrome 1+
  • Firefox 1.5+
  • Safari 3.2+
  • Edge 所有版本
  • IE 9+

最佳实践

1. 保持选择器简洁

/* 推荐 - 简洁的选择器 */
.element:not(.excluded) {
  /* 样式 */
}

/* 不推荐 - 复杂的选择器 */
.container .sidebar .menu .item:not(.active):not(.disabled) {
  /* 样式 */
}

2. 合理使用否定选择器

/* 推荐 - 合理使用 */
.nav a:not(.active) {
  opacity: 0.8;
}

/* 不推荐 - 过度使用 */
*:not(.class1):not(.class2):not(.class3) {
  /* 样式 */
}

3. 考虑性能影响

/* 推荐 - 性能更好的选择器 */
.container > *:not(.excluded) {
  /* 样式 */
}

/* 不推荐 - 性能较差的选择器 */
*:not(.excluded) {
  /* 样式 */
}

4. 提供降级方案

/* 推荐 - 提供降级方案 */
.element {
  /* 基础样式 */
}

.element:not(.excluded) {
  /* 增强样式 */
}

/* 不推荐 - 没有降级方案 */
.element:not(.excluded) {
  /* 所有样式 */
}

常见问题解决

1. 选择器不生效

/* 检查选择器是否正确 */
.element:not(.class) {
  /* 样式 */
}

/* 确保类名匹配 */
<div class="element excluded">
  /* 不会被选择 */
</div>

2. 性能问题

/* 解决方案 - 优化选择器 */
.container > *:not(.excluded) {
  /* 样式 */
}

/* 避免使用通配符 */
*:not(.excluded) {
  /* 样式 */
}

3. 兼容性问题

/* 解决方案 - 提供降级方案 */
.element {
  /* 基础样式 */
}

@supports selector(:not(.class)) {
  .element:not(.excluded) {
    /* 增强样式 */
  }
}

总结

:not() 否定伪类选择器是 CSS3 中一个功能强大且灵活的选择器:

主要特点:

  • 选择不匹配指定选择器的元素
  • 可以接受任何有效的 CSS 选择器
  • 支持嵌套和组合使用
  • 简化 CSS 代码编写

实际应用:

  • 排除特定样式的元素
  • 表单样式精确控制
  • 列表样式优化
  • 链接样式分类
  • 网格布局排除
  • 导航菜单样式

最佳实践:

  • 保持选择器简洁
  • 合理使用否定选择器
  • 考虑性能影响
  • 提供降级方案
  • 避免过度使用

局限性:

  • 不能嵌套使用
  • 不能选择伪元素
  • 某些伪类不支持

优势:

  • 简化代码编写
  • 提高代码可维护性
  • 减少类名使用
  • 增强样式控制精度

掌握 :not() 否定伪类选择器,能够让我们更精确地控制元素样式,避免编写冗长的选择器,大大提高 CSS 代码的可维护性和灵活性。