CSS Container Queries 实战:真正解决组件级响应式
做了好几年前端,媒体查询(Media Query)一直有个让人不爽的地方:它只能根据视口宽度来调整样式。但实际开发中,一个组件可能在大屏的侧边栏里宽度只有 300px,在小屏下全宽反而有 375px。视口宽度一样,组件的实际空间完全不同。
Container Queries 解决的就是这个问题。它在 2023 年底拿到了所有主流浏览器的支持,到 2025 年已经成为我日常开发中用得最多的 CSS 特性之一。
基本用法
/* 定义一个容器 */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* 根据容器的宽度调整样式 */
@container card (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
.card-image {
width: 200px;
flex-shrink: 0;
}
}
@container card (max-width: 399px) {
.card {
display: block;
}
.card-image {
width: 100%;
margin-bottom: 1rem;
}
}
container-type: inline-size 表示容器的宽度可以作为查询条件。container-name 是可选的,用来区分不同的容器。
实际项目中的场景
1. 卡片组件
这是我用得最多的场景。同一个卡片组件,放在首页全宽展示和放在侧边栏窄空间里,布局自动切换:
<!-- 首页:卡片容器很宽,水平布局 -->
<div class="card-wrapper" style="max-width: 800px">
<div class="card">...</div>
</div>
<!-- 侧边栏:卡片容器很窄,垂直布局 -->
<div class="card-wrapper" style="max-width: 280px">
<div class="card">...</div>
</div>
不用传 props 控制布局模式,CSS 自己就能搞定。组件的使用者不需要关心布局逻辑。
2. 导航栏
顶部导航在桌面端是水平菜单,在移动端抽屉里是垂直菜单。这两个场景其实都是同一个导航组件,只是容器宽度不同:
.nav-container {
container-type: inline-size;
}
@container (min-width: 600px) {
.nav {
flex-direction: row;
}
}
@container (max-width: 599px) {
.nav {
flex-direction: column;
}
}
3. 表格组件
大容器里表格展示所有列,小容器里隐藏次要列:
.table-container {
container-type: inline-size;
}
@container (max-width: 500px) {
.table .col-secondary {
display: none;
}
}
container-type 的三种值
.wrapper {
/* 只跟踪宽度 */
container-type: inline-size;
/* 只跟踪高度 */
container-type: size;
/* 宽高都跟踪 */
container-type: size;
}
inline-size 的性能比 size 好很多,因为它只需要监控一个方向。大部分情况下 inline-size 就够了,size 只在极少数需要根据高度做调整的场景下使用。
container query units
这个是比较新的功能,允许用容器尺寸作为单位:
.card-wrapper {
container-type: inline-size;
}
.card {
/* cqw = container query width,1cqw = 容器宽度的 1% */
font-size: clamp(14px, 2cqw, 20px);
padding: 2cqw;
}
这样字体大小和间距会随着容器大小自动缩放。以前要实现这种效果只能用 vw 单位配合 calc 算,现在直接用 cqw 就行。
和 Tailwind CSS 配合
Tailwind CSS v3.2+ 支持 Container Queries。用 @tailwindcss/container-queries 插件:
<div class="@container">
<div class="@md:flex @md:gap-4">
<div class="@md:w-48">...</div>
<div>...</div>
</div>
</div>
语法和普通的响应式前缀类似,前面加个 @ 就行。
性能注意事项
Container Queries 的性能开销比 Media Query 大一些,因为浏览器需要实时监控容器尺寸的变化。不过在实际使用中,我还没遇到过性能问题。有两个建议:
- 尽量用
inline-size而不是size - 避免在动画元素上使用 container query(会触发频繁重排)
浏览器兼容性
到 2025 年,所有主流浏览器都支持了。Safari 从 16.0 开始支持,Chrome 从 105 开始,Firefox 从 110 开始。基本上不需要考虑兼容性问题了。
写在最后
Container Queries 是 CSS 近年来最实用的特性之一。它让组件的样式可以真正与自身所处空间关联,而不是被迫依赖视口宽度。项目里大量用上之后,组件的复用性明显提高了,因为不用再通过 props 传各种布局模式了。