容器查询与媒体查询联用,组件响应式设计新思路
过去十几年,响应式设计的默认答案几乎都是媒体查询:视口宽度到了某个断点,就调整栅格、导航和组件布局。但组件化开发普及后,这个默认答案开始失灵。一个卡片组件放在主内容区时宽 720px,放进侧栏只有 280px,放进弹窗可能 400px,而视口宽度始终是 1440px。媒体查询只能告诉组件“浏览器多宽”,却无法告诉它“你现在多宽”。
容器查询改变了这一点。组件可以声明自己作为查询容器,内部样式根据父容器宽度变化。它让组件从“页面宽度的函数”变成“自身可用空间的函数”。但容器查询并非媒体查询的替代品,两者联用,才更接近现代响应式设计的完整答案。
为什么媒体查询不够用了
媒体查询假设组件宽度与视口宽度强相关。这在整页布局时代成立,在组件复用时失效。组件散落在不同容器里,如果内部仍按视口断点切换布局,就会出现窄容器里显示桌面布局、宽容器里过早折叠的尴尬。更麻烦的是,组件被复用时必须携带页面级断点假设,耦合重、测试难。
容器查询:让组件对自己负责
容器查询的核心是:父级声明 `container-type: inline-size`,子级用 `@container` 基于容器宽度设置样式。例如卡片在窄容器里纵向堆叠,宽容器里变成左图右文。断点应基于内容而非设备:标题何时换行、按钮组何时拥挤、图片何时需要并排,才是断点依据。这样组件可以被放进任何位置,仍然保持合理形态。
媒体查询仍然不可替代
容器查询解决局部,媒体查询解决全局与环境。页面栅格、导航折叠、侧边栏显隐、打印样式、暗色模式、`prefers-reduced-motion`、`hover`/`pointer` 能力,这些都不是某个组件容器能感知的。它们属于视口、设备或用户偏好,应该继续交给媒体查询。把媒体查询从组件内部抽离,放到布局层和全局层,反而更清晰。
联用策略:分层响应式
可以按三层组织:第一层是页面布局层,用媒体查询控制整体栅格、区域排列和导航形态;第二层是组件层,用容器查询控制组件内部结构、密度和元素显隐;第三层是环境偏好层,用媒体查询配合 `prefers-color-scheme`、`prefers-reduced-motion`、`print` 等,保证可访问性和多端体验。
.layout {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 64rem) {
.layout { grid-template-columns: 16rem 1fr; }
}
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 30rem) {
.card {
display: grid;
grid-template-columns: 120px 1fr;
}
}
@media (prefers-reduced-motion: reduce) {
* { animation: none !important; }
}
实践中的注意点
不要无脑给所有元素加 `container-type`,它可能影响绝对定位和尺寸计算,按需使用即可。容器查询单位如 `cqw`、`cqh` 很有用,但也要理解其参照对象。嵌套容器时,最近祖先容器生效,复杂场景建议命名容器。设计系统里最好区分“视口断点”和“容器断点”两套 token,并在组件文档中标注最小可用宽度和推荐宽度。旧浏览器可用 `@supports` 做渐进增强,而不是强行抹平差异。
结语
容器查询不是媒体查询的终结者。更合理的方向是分层:页面看视口,组件看容器,体验看用户偏好。媒体查询负责全局布局和环境适配,容器查询负责组件内部的自适应。两者联用,组件才能真正可复用,页面也才能在不同上下文中保持稳定与灵活。
转载请注明出处,版权归原作者所有。
管理员





