:has() 实战
真实项目中的 :has() 应用案例
实战应用场景
:has() 伪类在实际项目中有着广泛的应用场景。
通过根据子元素的状态来改变父元素的样式,我们可以实现许多以前需要 JavaScript 才能完成的功能。
本页面展示了 4 个真实的应用案例,涵盖了表单验证、卡片状态管理、导航菜单和购物车等常见场景。 这些案例都是可以直接应用到实际项目中的实用技巧。
- 表单验证 - 根据输入框状态改变表单容器样式
- 卡片状态 - 根据内容和选中状态调整卡片布局
- 导航菜单 - 智能高亮和子菜单指示
- 购物车 - 根据商品数量显示不同状态
案例 1: 表单验证状态
使用 :has() 根据表单内输入框的验证状态,动态改变表单容器的样式,提供实时的视觉反馈。
💡 尝试填写表单,观察表单容器的边框和背景色变化
/* 表单包含无效输入时显示错误样式 */
.validation-form:has(input:invalid) {
border-color: red;
background: #fee;
}
/* 显示错误提示 */
.validation-form:has(input:invalid) .form-status.error {
display: block;
}
/* 表单全部有效时显示成功样式 */
.validation-form:has(input:valid):not(:has(input:placeholder-shown)) {
border-color: green;
background: #efe;
}
/* 显示成功提示 */
.validation-form:has(input:valid):not(:has(input:placeholder-shown)) .form-status.success {
display: block;
}
/* 优势:无需 JavaScript 即可实现实时验证反馈 */
案例 2: 卡片状态管理
根据卡片内容和选中状态,动态调整卡片的样式和布局。这在任务列表、商品列表等场景中非常实用。
智能手机
最新款旗舰手机,性能强劲
¥4,999
无线耳机
降噪耳机,音质出色(无图片)
¥1,299
笔记本电脑
轻薄便携,适合办公
¥6,999
智能手表
健康监测,运动追踪(无图片)
¥2,499
💡 点击卡片右上角的复选框,观察卡片样式变化。有图片的卡片布局也不同。
/* 卡片包含选中复选框时高亮 */
.product-card:has(input[type="checkbox"]:checked) {
background: lightgreen;
border-color: green;
box-shadow: 0 4px 12px rgba(0, 255, 0, 0.2);
transform: scale(1.02);
}
/* 显示选中标签 */
.product-card:has(input:checked)::before {
content: '✓ 已选中';
position: absolute;
top: 15px;
left: 15px;
background: green;
color: white;
padding: 4px 12px;
border-radius: 20px;
}
/* 卡片包含图片时调整布局 */
.product-card:has(img) {
display: grid;
grid-template-rows: auto 1fr auto;
gap: 15px;
}
/* 多种状态组合:根据内容和选中状态动态调整 */
案例 3: 导航菜单高亮
使用 :has() 实现智能导航菜单,根据当前页面链接自动高亮父级导航项,并为包含子菜单的项显示箭头。
💡 "产品中心"包含当前激活的子链接,因此自动高亮并展开。有子菜单的项显示箭头。
/* 包含当前页面链接的导航项高亮 */
.smart-nav li:has(a.active) {
background: lightgreen;
border-radius: 8px;
padding: 8px;
}
/* 包含子菜单的导航项显示箭头 */
.smart-nav li:has(ul) > a::after {
content: '▼';
float: right;
transition: transform 0.3s;
}
/* 展开包含激活链接的子菜单 */
.smart-nav li:has(a.active) ul {
max-height: 500px;
}
/* 旋转箭头 */
.smart-nav li:has(a.active) > a::after {
transform: rotate(180deg);
}
/* 优势:父级导航自动感知子链接状态,无需手动添加类 */
案例 4: 购物车状态
根据购物车中是否有商品,动态显示不同的状态和操作按钮。这是电商网站中非常常见的场景。
购物车
0 件商品测试功能:添加商品到购物车
💡 添加商品到购物车,观察空状态和有商品状态的切换。结算按钮只在有商品时显示。
/* 购物车为空时显示提示 */
.shopping-cart:not(:has(.cart-item)) .empty-message {
display: block;
}
/* 隐藏空购物车的商品列表 */
.shopping-cart:not(:has(.cart-item)) .cart-items {
display: none;
}
/* 隐藏空购物车的数量标签 */
.shopping-cart:not(:has(.cart-item)) .cart-count {
display: none;
}
/* 购物车有商品时显示结算按钮 */
.shopping-cart:has(.cart-item) .cart-actions {
display: flex;
}
/* 优势:根据商品数量自动切换状态,无需手动管理类名 */
浏览器兼容性
:has() 是一个相对较新的 CSS 特性,主流现代浏览器已经支持。
| 浏览器 | 版本 | 支持状态 |
|---|---|---|
| Chrome / Edge | 105+ | ✓ 完全支持 |
| Firefox | 121+ | ✓ 完全支持 |
| Safari | 15.4+ | ✓ 完全支持 |
| Opera | 91+ | ✓ 完全支持 |
| IE 11 | - | ✗ 不支持 |
如果需要支持旧版浏览器,可以使用 @supports 检测 :has() 支持情况,
并提供降级方案(如使用 JavaScript 或传统的类名管理)。
/* 检测 :has() 支持 */
@supports selector(:has(*)) {
.card:has(input:checked) {
/* 支持 :has() 的样式 */
}
}
@supports not selector(:has(*)) {
.card.selected {
/* 降级方案:使用类名 */
}
}
更多兼容性信息请访问: Can I Use - :has()
实战总结
通过这 4 个实战案例,我们看到了 :has() 在真实项目中的强大应用:
- 表单验证 - 无需 JavaScript 即可实现实时验证反馈
- 卡片管理 - 根据内容和状态自动调整样式和布局
- 智能导航 - 父级菜单自动感知子链接状态
- 购物车 - 根据商品数量动态切换空/非空状态
:has() 让我们能够用纯 CSS 实现许多以前需要 JavaScript 才能完成的功能,
大大简化了代码,提升了性能和可维护性。在支持的浏览器中,它是一个非常值得使用的现代特性。