做过组件库的人都踩过这个坑——同一个组件在侧边栏和主内容区需要不同布局,以前只能靠传 prop 或写 class 覆盖,今天容器查询让组件自己感知自己被放在了哪里
做过组件库的人都踩过这个坑——同一个卡片组件,放在侧边栏和放在主内容区,需要完全不同的布局,但用媒体查询写死的断点永远对不上所有场景。最后要么给组件多传一个 prop 让他自己判断,要么写一堆 class 覆盖。
容器查询把这件事彻底原生化了。
核心能力:让组件感知自己容器的大小,而不是 viewport 的大小。写法很简单,先在父容器上声明 container-type,然后在查询里针对容器宽度写样式:
.card-wrapper {
container-type: inline-size;
container-name: card;
}
.card {
display: flex;
flex-direction: column;
}
@container card (width > 480px) {
.card {
flex-direction: row;
}
}
同一个 HTML,不需要任何 JS,也不需要传 prop,丢进侧边栏就是纵向布局,丢进主内容区就是横向布局。
还有容器单位:cqi(容器内联方向单位)、cqw(容器宽度单位),让字体和间距直接相对于容器宽度做流式计算,不需要 JS 监听 resize。
性能数据是架构层面最值得关注的点:基于 ResizeObserver 的 JS 响应式方案,渲染性能比原生容器查询慢约 35%,而且还会额外产生布局抖动。容器查询是浏览器原生实现,没有这个开销。
三类容器查询:尺寸查询(container-type: inline-size)最成熟,2026 年所有主流浏览器全部支持;样式查询(@container style(--theme: dark))查自定义属性值,支持还在逐步完善,适合渐进增强;滚动状态查询(@container scroll-state(scrolled-y))可以让 header 在滚动时自动加阴影,一个 JS 事件监听都不需要。
实操迁移路径,按步骤来:
第一步,确认要迁移的组件——卡片、媒体对象、可选列的数据表格、导航模式,这些在不同布局上下文里行为不同的组件收益最高。
第二步,给包裹元素加上 container-type: inline-size,有嵌套容器或需要精确指定祖先时加上 container-name。
第三步,把媒体查询阈值转成容器查询阈值。注意:媒体查询的断点是 viewport 宽度,容器查询的断点是组件自身布局的拐点,通常数值比媒体查询小很多。
第四步,删掉 ResizeObserver 或相关 JS 库,浏览器原生处理,不需要运行时监听。
第五步,在各种布局上下文里测试——侧边栏、满宽、弹窗、网格单元格,每个组合都过一遍。
Tailwind v4 已经内置了容器查询语法,用 @container 配合命名容器,不需要写一行自定义 CSS。已有的组件库改成按需引入,不需要全量迁移。
宏观布局用媒体查询,微观组件用容器查询——这两件事不是替代关系,是分工关系。
评论区
登录后可评论。