配了八年响应式,每次都要问「屏幕多宽」——今天 CSS 自己会问「容器多大」了,@container 把这件事彻底原生化了
配了八年响应式,每次写布局都要先问「屏幕多宽」——媒体查询帮你回答了屏幕有多宽,但它永远回答不了这个组件自己有多少空间。把同一个卡片塞进 1200px 主内容区是横排,塞进 280px 侧边栏就崩了——媒体查询束手无策,只能靠 JS 硬撑或者写一堆 .card--small 变体。今天 @container 把这件事彻底变了:CSS 终于可以问「我的容器给了我多少空间」,然后自己决定怎么排版。
媒体查询解决不了的问题
传统媒体查询是屏幕级的。@media (min-width: 768px) 问的是「浏览器窗口」有多宽,不是「这个卡片所在的格子」有多宽。
同一个卡片组件,会出现在:
- 全宽 Hero 区 → 横排
- 三栏产品网格 → 横排
- 两栏对比区 → 横排
- 280px 侧边栏 → 必须竖排
但视口可能是 1440px。媒体查询在所有场景下都返回「宽屏」,于是侧边栏里的卡片就崩了。
以前的解法:ResizeObserver + JS 动态切换 class,或者写一堆 variantprops。管用,但 CSS 不该靠 JS 看着。
@container 的解法:问容器,不问屏幕
第一步,给父级加 container-type:
.card-wrapper {
container-type: inline-size;
container-name: card;
}
第二步,用 @container 写条件:
.card { display: flex; flex-direction: column; }
@container card (min-width: 400px) {
.card {
flex-direction: row; /* 容器 ≥ 400px,自动切横排 */
}
}
同一个 HTML,同一个 CSS,卡片放进 1200px 主内容区是横排,放进 280px 侧边栏自动变竖排——JS 零行,媒体查询管不着的它管了。
三类容器查询,2026 年全部就绪
尺寸查询(最常用):
@container (width > 480px) { ... }
@container card (min-width: 600px) { ... }
支持范围语法 >、<、= 和逻辑组合 and / or / not。
Style 查询(2026 年稳定,所有主流引擎支持):
.card-wrapper { --theme: dark; }
@container style(--theme: dark) {
.card { background: #1a1a2e; color: #eee; }
}
Query 的是 CSS 变量,不是 computed style——目前只能查 custom properties,但这个能力已经让纯 CSS 主题切换成为可能。
Scroll-State 查询(最新,2026 年正式进 Baseline):
@container scroll-state(scrolled-y) {
.header { box-shadow: 0 2px 8px rgba(0,0,0,0.2); }
}
纯 CSS 响应滚动状态,不需要 onscroll 监听器。
容器单位:cqi / cqw,流动排版专用
和 vw/vh 类似,但基准是容器不是视口:
.card-title {
font-size: clamp(1rem, 5cqi, 2.5rem); /* 随容器宽度缩放 */
}
.card-body {
padding: 4cqw 6cqw; /* 内边距也随容器走 */
}
cqi 是 inline 轴的 1%,支持书写模式(竖排文字场景下 inline 轴是垂直的);cqw 永远是物理宽度。实战中 cqi 用得更多。
性能:比 ResizeObserver 快 35%
codercops.com 的实测:把 47 个组件的设计系统从媒体查询迁移到容器查询,删掉了 23 个 variantprops 和对应的 JS 逻辑。一家 SaaS 团队在大型仪表盘里用了几十个容器,中档笔记本每次布局重算开销约 10–15ms——在现代浏览器(Chromium/Gecko/WebKit 均已优化 containment 逻辑)里,这个成本完全可以接受。
实战建议:
- 只给真正需要响应容器大小的组件加
container-type,不要给每个 div 都加 - 优先用
inline-size(只管宽度),不用size(宽高都管)——后者有额外的布局约束开销 - 避免在动画过程中改变容器宽高(触发 query 重新计算)
媒体查询和容器查询怎么分工
不是二选一,是分工:
| 场景 | 用什么 |
|---|---|
| 全页栅格:1栏→3栏 | @media |
| 导航栏在移动端收起 | @media |
| 卡片从竖排变横排 | @container |
| 侧边栏小部件自适应 | @container |
| 系统暗色模式 | @media (prefers-color-scheme: dark) |
| 组件根据 CSS 变量切换主题 | @container style() |
下一步:5 分钟迁移一个卡片组件
- 给卡片外层加
container-type: inline-size; - 把原来针对该卡片的媒体查询换成
@container(宽度阈值按卡片实际需求设,不要照抄全站断点) - 删掉对应的 JS ResizeObserver 逻辑
迁移完之后,这个卡片在任何布局上下文里都能自己适应——放进 Modal、侧边栏、主内容区,都不需要改一行 HTML 或加一个 class。
来源:MDN CSS Container Queries 官方文档 + codercops.com 2026 State of CSS(2400行删除案例)+ thelinuxcode.com 性能实测 + dev.to 三类容器查询实战 + layoutscene.com 2026 完整指南
评论区
登录后可评论。