CSS 媒体查询和容器查询有什么区别?响应式组件为什么不能只看屏幕宽度?
下面是一段教学用的模拟面试。
🧑💻 面试官: 媒体查询和容器查询有什么区别?
🙋♂️ 我: 都是按宽度切换样式。屏幕大就横排,屏幕小就竖排。
🧑💻 面试官: 屏幕没变,卡片从主栏搬到了侧栏。它应该继续横排吗?
🙋♂️ 我: 那应该看侧栏给它留了多大空间。
🧑💻 面试官: 你准备查询谁的宽度?可以让卡片根据自己的宽度改变自己吗?
这道题要分清的是「参照对象」:页面按视口安排,组件按自己获得的空间安排。
面试速答(60 秒版)
媒体查询用于判断视口尺寸、输入方式、用户偏好等条件。其中宽度查询主要看浏览器视口,不是当前组件的宽度。
尺寸容器查询则根据祖先查询容器的尺寸调整组件样式。同一张卡片放在宽主栏和窄侧栏里,就可以采用不同布局,不必等整张页面一起跨过断点。
实现时,先在合适的祖先上声明 container-type,再用 @container 设置后代的样式。祖先提供稳定的尺寸参照,后代根据它调整布局。
实际项目里,两种方式可以一起用:媒体查询控制页面骨架,容器查询控制可复用组件。

图:页面看视口,卡片看空间。
知识点详解:卡片需要知道的是可用空间,不是屏幕有多大
同一块屏幕,也会有两种布局需求
假设视口宽度是 1200px,主栏有 800px,侧栏只有 280px。我们把同一种课程卡片放到这两个位置。
主栏里的卡片可以左边放图片、右边放介绍。侧栏如果还这么排,文字就会被挤得很窄。问题不是屏幕小,而是这张卡片实际获得的空间小。
如果只写 @media (min-width: 1000px),两张卡片会同时进入“大屏模式”。媒体查询没有出错,是我们问错了对象。
给组件找一个明确的参照
在卡片外面放一层 .card-slot,由它提供查询尺寸:
.card-slot {
container-type: inline-size;
container-name: course-card;
}
.card {
display: grid;
grid-template-columns: 1fr;
}
@container course-card (min-width: 500px) {
.card {
grid-template-columns: 160px 1fr;
}
}
默认竖排;名为 course-card 的查询容器宽到 500px 后,里面的卡片改成两列。通常的水平书写方向里,inline-size 对应横向尺寸。CSS 是浏览器的同一套规则,不需要翻译成 TS 和 Python。
这里,祖先 .card-slot 提供参照,后代 .card 接受样式。没有指定名字时,会寻找符合查询要求的最近祖先容器;名字可以减少嵌套后“到底查了哪层”的误会。

图:祖先提供尺寸,后代调整布局。
为什么还要声明 container-type?
如果祖先宽度由子元素撑开,子元素又根据祖先宽度决定自己多宽,就容易出现互相依赖。
声明尺寸查询容器,会建立相应的尺寸隔离条件,让浏览器能够稳定地计算查询。因此它不只是给元素贴名字,还会影响尺寸计算。不能不看布局,就给每层都加上。MDN 容器查询说明介绍了这些条件。
实际做法通常是让外层 Grid 或 Flex 决定容器获得的宽度,再由内部组件响应这个宽度。也不要把“子元素查询祖先”误写成“元素查询自己,再修改自己”。
两种方式各管哪部分?
页面从双栏变单栏,通常看视口比较自然;卡片内部的标题、图片、按钮怎样排列,更适合看它获得的空间。
减少动画、深浅配色等用户偏好,也是媒体查询的重要用途。容器查询不是把媒体查询全部淘汰了,它们解决的问题并不相同。
面试官继续追问
怎么验证没有查错容器?
固定浏览器宽度,只改变卡片外层的宽度。卡片应该跟着容器跨过断点。再固定容器宽度、改变视口,它不应该只因视口变动就切换这条容器规则。
宽度变小了,为什么还是横排?
先查查询容器、名字和实际计算尺寸,再查规则有没有被其他样式覆盖。不要一上来就反复改断点。
面试速记卡
- 媒体查询:视口、设备能力和用户偏好等条件。
- 尺寸容器查询:符合条件的祖先查询容器尺寸。
- 层级:祖先提供参照,后代响应条件。
- 选型:页面骨架看视口,可复用组件看可用空间。
- 验证:分别改变视口与容器,不把两者一起改。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →