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 这个组合值得试试。
评论区
登录后可评论。