
利用 CSS :has() 伪类检测子元素数量,动态调整 grid-template-columns,实现“有两列则显示双列,仅一子项时自动收缩为居中单列”的响应式网格布局。
利用 css `:has()` 伪类检测子元素数量,动态调整 grid-template-columns,实现“有两列则显示双列,仅一子项时自动收缩为居中单列”的响应式网格布局。
在构建灵活的产品卡片网格时,常需兼顾多项目与少项目场景:双卡片时应并排展示,单卡片时则需居中、不预留空白列。传统方案(如 JavaScript 判断或额外 class 控制)增加了复杂度,而现代 CSS 提供了更优雅的纯样式解法——:has() 伪类。
核心思路是:默认设置双列网格(grid-template-columns: repeat(2, 300px)),再通过 .cards:has(:only-child) 选择器精准匹配仅含一个直接子元素的容器,并将其列定义覆盖为单列:
.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: 1rem;
border-radius: 4px;
text-align: center;
}
/* 当 .cards 内仅有唯一子元素时,切换为单列 */
.cards:has(:only-child) {
grid-template-columns: 300px;
justify-items: center; /* 确保单列内容水平居中 */
}✅ 关键说明:
-
:only-child匹配的是既是子元素又是其父元素唯一子节点的元素,因此.cards:has(:only-child)可靠识别仅含一个.product-card的情况; - 单列时无需
repeat(1, 300px),直接写300px更简洁; - 添加
justify-items: center可确保单列卡片在网格轨道内居中(尤其当容器宽于 300px 时); - 若需兼容旧版浏览器(如 Safari :has() 尚不支持,此时建议回退至 JavaScript 动态添加 class(例如
cards--single),或使用:nth-child(1):nth-last-child(1)组合模拟(但语义性稍弱)。
该方案零 JS、语义清晰、维护成本低,是现代 CSS 布局能力的典型实践。
立即学习“前端免费学习笔记(深入)”;


















