选择器组合实战

多个现代选择器组合使用的复杂案例

组合选择器的威力

单独使用现代选择器已经很强大,但当我们将 :has():is():where():not() 等选择器组合使用时,可以实现更加复杂和智能的样式控制。

本页面展示了 4 个真实的复杂案例,演示如何通过组合多个现代选择器来解决实际项目中的样式需求。 这些案例涵盖了表格、表单、布局和导航等常见场景。

  • 响应式表格 - 根据数据状态和选中状态动态调整表格样式
  • 动态表单验证 - 组合多个选择器实现复杂的表单验证逻辑
  • 条件样式布局 - 根据内容存在与否自动调整布局
  • 智能导航 - 多级导航的自动状态管理

案例 1: 响应式表格样式

使用 :has():not() 组合,根据表格行的数据状态和选中状态, 动态显示批量操作按钮、高亮错误行、显示空状态提示。

效果预览 - 点击复选框或按钮测试
用户名 邮箱 状态 积分
张三 zhangsan@example.com 正常 1250
李四 invalid-email 正常 890
王五 wangwu@example.com 正常 2100
赵六 zhaoliu@example.com 已禁用 0

暂无数据

表格中还没有任何数据

💡 尝试选中行、添加/删除数据,观察批量操作栏、错误高亮和空状态的自动切换

/* 表格包含选中行时显示批量操作 */
.data-table-container:has(tr.selected) .bulk-actions {
  display: flex;
}

/* 表格行包含错误数据时高亮 */
.data-table tbody tr:has(.error-cell) {
  background: var(--error-light);
  border-left: 4px solid var(--error);
}

/* 表格为空时显示提示 */
.data-table-container:not(:has(tbody tr)) .empty-table-message {
  display: block;
}

.data-table-container:not(:has(tbody tr)) .data-table {
  display: none;
}

/* 优势:
   1. 无需 JavaScript 管理 UI 状态
   2. 自动响应数据变化
   3. 代码简洁易维护 */

案例 2: 动态表单验证

组合 :has():not():is() 实现复杂的表单验证逻辑, 必填项未填写时自动禁用提交按钮,并提供实时验证反馈。

效果预览 - 填写表单查看验证效果

用户注册

表单填写完整,可以提交

基本信息

用户名必须至少包含 3 个字符
请输入有效的电子邮箱地址
请输入 11 位手机号码

账户安全

密码必须至少包含 6 个字符
请再次输入相同的密码

其他信息

个人简介为可选项

💡 尝试填写表单,注意提交按钮在必填项未填写时自动禁用,输入无效数据时显示警告

/* 表单包含未填写的必填项时禁用提交按钮 */
.complex-form:has(input[required]:placeholder-shown) .submit-button,
.complex-form:has(select[required][value=""]) .submit-button {
  opacity: 0.5;
  pointer-events: none;
  cursor: not-allowed;
}

/* 表单包含无效输入时显示警告 */
.complex-form:has(:is(input, textarea):invalid:not(:placeholder-shown)) .form-warning {
  display: flex;
}

/* 表单全部有效时显示成功提示 */
.complex-form:has(input[required]:not(:placeholder-shown):valid)
             :has(select[required]:not([value=""]))
             :not(:has(input:invalid))
             :not(:has(textarea:invalid)) .form-success {
  display: flex;
}

/* 优势:
   1. 复杂验证逻辑完全由 CSS 实现
   2. 自动响应用户输入
   3. 无需编写验证 JavaScript */

案例 3: 条件样式布局

使用 :has():not() 根据内容的存在与否自动调整布局, 实现智能的响应式设计,无需 JavaScript 或媒体查询。

效果预览 - 点击按钮添加/移除侧边栏

主内容区

这个布局会根据侧边栏的存在与否自动调整主内容区的宽度。 同时,下方的内容网格会根据项目数量自动调整列数。

数据分析

查看统计数据

趋势报告

分析增长趋势

项目管理

管理项目进度

💡 尝试切换侧边栏和添加/移除内容项,观察布局如何自动调整

/* 根据是否有侧边栏调整主内容宽度 */
.page-container:has(.page-sidebar) .page-main {
  width: calc(100% - 270px);
}

.page-container:not(:has(.page-sidebar)) .page-main {
  width: 100%;
  max-width: 100%;
}

/* 根据内容数量调整网格列数 */
/* 只有 1-2 个项目时单列 */
.content-grid:has(.content-item:nth-child(1))
             :not(:has(.content-item:nth-child(3))) {
  grid-template-columns: 1fr;
}

/* 有 3-4 个项目时两列 */
.content-grid:has(.content-item:nth-child(3))
             :not(:has(.content-item:nth-child(5))) {
  grid-template-columns: repeat(2, 1fr);
}

/* 有 5 个或更多项目时三列 */
.content-grid:has(.content-item:nth-child(5)) {
  grid-template-columns: repeat(3, 1fr);
}

/* 优势:
   1. 布局自动响应内容变化
   2. 无需 JavaScript 或媒体查询
   3. 代码简洁直观 */

案例 4: 智能导航

组合 :has():is():not() 实现智能的多级导航系统, 自动显示子菜单箭头、高亮当前页面、管理展开/收起状态。

效果预览 - 点击链接查看导航状态

💡 点击按钮切换当前页面,观察导航如何自动高亮父级菜单并展开相关子菜单

/* 当前页面的导航项高亮 */
.smart-navigation a.active {
  background: var(--primary);
  color: white;
}

/* 包含当前页面链接的父级导航项高亮 */
.smart-navigation li:has(a.active) > a:first-child:not(.active) {
  background: var(--primary-light);
  color: var(--primary-dark);
  border-left: 4px solid var(--primary);
}

/* 导航项包含子菜单时显示箭头 */
.smart-navigation li:has(ul) > a::after {
  content: '▼';
  position: absolute;
  right: 16px;
  transition: transform 0.3s;
}

/* 展开包含激活链接的子菜单 */
.smart-navigation li:has(a.active) > ul {
  max-height: 500px;
}

/* 旋转箭头 */
.smart-navigation li:has(a.active) > a::after {
  transform: rotate(180deg);
}

/* 包含激活子项的多级导航高亮 */
.smart-navigation li:has(li:has(a.active)) > a:first-child:not(.active) {
  background: var(--info-light);
  color: var(--info-dark);
  border-left: 4px solid var(--info);
}

/* 优势:
   1. 多级导航自动管理状态
   2. 父级菜单自动感知子链接
   3. 无需手动添加类名
   4. 支持任意深度的嵌套 */

组合选择器的最佳实践

通过这 4 个案例,我们看到了现代选择器组合使用的强大能力。以下是一些最佳实践建议:

✅ 推荐做法

  • 优先使用 CSS 实现状态管理
  • 组合选择器解决复杂需求
  • 保持选择器简洁易读
  • 添加注释说明复杂逻辑
  • 考虑浏览器兼容性
  • 提供降级方案

❌ 避免做法

  • 过度嵌套选择器
  • 过于复杂的组合逻辑
  • 忽略性能影响
  • 不考虑可维护性
  • 完全依赖现代选择器
  • 忽略无障碍访问

🎯 性能考虑

虽然现代选择器非常强大,但在使用时也要注意性能:

  • :has() 选择器可能影响性能,避免在大型列表中过度使用
  • 尽量将 :has() 应用在较小的作用域内
  • 避免过深的嵌套和过于复杂的组合
  • 使用浏览器开发工具监控性能
  • 在必要时考虑使用 JavaScript 替代

⚡ 实战技巧

  1. 渐进增强 - 先实现基础功能,再用现代选择器增强
  2. 特性检测 - 使用 @supports 检测浏览器支持
  3. 降级方案 - 为不支持的浏览器提供替代方案
  4. 测试验证 - 在多个浏览器中测试效果
  5. 文档记录 - 为复杂选择器添加详细注释

浏览器兼容性

本页面使用的现代选择器在主流浏览器中的支持情况:

选择器 Chrome Firefox Safari Edge
:has() ✓ 105+ ✓ 121+ ✓ 15.4+ ✓ 105+
:is() ✓ 88+ ✓ 78+ ✓ 14+ ✓ 88+
:where() ✓ 88+ ✓ 78+ ✓ 14+ ✓ 88+
:not() (复杂) ✓ 88+ ✓ 84+ ✓ 9+ ✓ 88+
⚠️ 兼容性建议

如果需要支持旧版浏览器,建议:

  • 使用 @supports 进行特性检测
  • 提供 JavaScript 降级方案
  • 使用 PostCSS 等工具进行转换
  • 考虑使用 polyfill(性能可能受影响)

更多兼容性信息请访问 Can I Use