CSS 终于能选父元素了——:has() 配合 Container Queries 让我把响应式组件做完整了

CSS 有一个困扰了十几年的问题:无法选择父元素。一个容器想知道自己里面有没有装图片从而调整样式,只能靠 JavaScript 来判断。但 :has() 改变了这件事件,再配合 Container Queries,响应式组件终于能做完整了。

:has() 是什么

:has() 是 CSS 选择器里的否定类,语法很简单——:has(selector) 意思是「包含这个选择器的元素」。比如说 .card:has(img) 就能选中所有包含图片的卡片,不需要 JavaScript,不需要额外的类名,CSS 自己就能检测到。

Container Queries 是什么

Container Queries 允许组件根据自己容器的大小来调整样式,而不是根据视口大小。这样同一个组件在不同地方可以有不同的表现。

两者配合能做什么

举一个具体的例子。用 Container Queries 做一个卡片网格,大屏幕三列,小屏幕一列:

.card-grid {
container-type: inline-size;
display: grid;
grid-template-columns: repeat(3, 1fr);
}

@container (max-width: 400px) {
.card-grid {
grid-template-columns: 1fr;
}
}

然后在卡片里用 :has() 来检测内容类型:

.card {
border-radius: 8px;
overflow: hidden;
}

/ 有图片的卡片,图片撑满 /
.card:has(img) {
display: flex;
flex-direction: column;
}

.card:has(img) img {
width: 100%;
height: 200px;
object-fit: cover;
}

/ 没图片的卡片,正常的文本间距 /
.card:not(:has(img)) {
padding: 16px;
}

这样,同一个 .card 类,在不同容器里自动呈现不同样式,不需要 JavaScript 计算,不需要额外的 CSS 类,CSS 自己就把响应式做完了。

这个组合为什么重要

之前响应式组件要靠 JavaScript 检测容器宽度、检测子元素类型,然后动态添加类名。现在 CSS 自己就能处理这两件事,组件真正变成了「自包含」的——响应式逻辑全在 CSS 里,不在 JavaScript 里。

需要注意什么

一个是性能。:has() 的性能在不同浏览器里有差异,复杂的 :has() 选择器可能影响渲染性能,写的时候注意控制复杂度。

另一个是浏览器支持。:has() 和 Container Queries 的浏览器支持都已经很好了,Chrome、Firefox、Safari、Edge 最新版都支持,生产环境可以直接用。

什么时候用

现在就可以用。如果你的项目需要做响应式组件,特别是那种「同一个组件在不同容器里有不同表现」的场景,:has() + Container Queries 这个组合值得试试。

评论区

0 条评论

登录后可评论。

阿柯·前端架构 1006 阅读