
本文介绍如何使用 :has() 伪类配合 CSS Grid,让容器在仅含一个子项时自动从两列切换为单列并居中显示,避免空白列占用空间,兼顾兼容性与语义化。
本文介绍如何使用 :has() 伪类配合 css grid,让容器在仅含一个子项时自动从两列切换为单列并居中显示,避免空白列占用空间,兼顾兼容性与语义化。
在构建产品卡片网格时,我们常希望布局具备“智能适应性”:当有两项内容时显示并排双列;当仅有一项时,自动收缩为居中的单列,而非保留右侧空白区域。传统方案(如 JavaScript 动态添加 class 或媒体查询)往往冗余或不够语义化。现代 CSS 提供了更优雅的纯样式解法——利用 :has() 伪类检测子元素数量,并动态调整 grid-template-columns。
核心思路是:默认定义双列布局,再通过选择器精准定位“仅含一个直接子元素”的 .cards 容器,并覆盖其列定义:
.content {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
}
.cards {
display: grid;
grid-template-columns: repeat(2, 300px);
column-gap: 8px;
margin: 1rem 0;
}
.product-card {
background-color: teal;
color: white;
padding: 16px;
border-radius: 4px;
text-align: center;
}
/* 关键:当 .cards 内仅有唯一子元素时,切换为单列 */
.cards:has(:only-child) {
grid-template-columns: 300px;
justify-content: center; /* 确保单列时水平居中(可选,增强健壮性) */
}
该方案优势显著:
- ✅ 零 JavaScript:完全基于 CSS,性能高效、维护成本低;
- ✅ 语义清晰:无需额外 class 或 DOM 操作,样式逻辑与结构自然耦合;
- ✅ 精准匹配:
:only-child确保仅当子元素是唯一且为直接子节点时生效,避免误触发。
需注意以下关键点:
-
浏览器兼容性:
:has()目前在 Chrome 105+、Firefox 119+、Safari 15.4+ 中已支持,但旧版 Safari 及 IE 不支持。生产环境建议搭配 Can I Use 数据评估,并考虑降级方案(如@supports检测 + 备用 Flex 布局); -
避免嵌套干扰:
:only-child匹配的是“父容器中唯一的直接子元素”,若.cards内存在注释、文本节点或隐藏元素,可能破坏匹配逻辑,建议确保子元素为纯净<div>;<li> <strong>宽度灵活性</strong>:<code>300px可替换为minmax(300px, 1fr)或1fr实现流体适配,但需同步调整:has()规则以保持一致性。
最终效果:双卡片时等宽并列,单卡片时独占居中,视觉平衡且代码简洁——这正是现代 CSS 布局能力的典型体现。











