代表性面试主题

前端面试:CSS 容器查询与媒体查询有什么区别?

前端中等
OfferCC 编辑团队发布 更新

题干

一个卡片组件会同时出现在主内容区、侧栏和网格中。请解释 CSS 容器查询与媒体查询的区别,写出按卡片容器宽度切换布局的 CSS,并说明容器建立、查询作用域、回退和测试方案。

题干与适用场景

一个卡片组件会同时出现在主内容区、侧栏和网格中。请解释 CSS 容器查询与媒体查询的区别,写出按卡片容器宽度切换布局的 CSS,并说明容器建立、查询作用域、回退和测试方案。

媒体查询根据视口或设备特征做判断;容器查询根据祖先查询容器的尺寸、样式或滚动状态做判断。GreatFrontEnd 的 CSS 面试资料直接把容器查询列为面试题,Hack Frontend 的 HTML/CSS 题单也覆盖该主题;MDN 文档说明了 container-type、@container 与容器查询单位的规范行为。本文不绑定具体公司。

面试官考察点

面试官看候选人能否先区分响应对象,再写出完整上下文。高质量回答应说明 container-type: inline-size 建立尺寸查询上下文,查询规则作用于后代而非容器本身,默认匹配最近的合格祖先,并解释为什么同一视口下不同卡片宽度需要容器查询。

还要检查候选人是否理解尺寸包含的副作用、命名容器的边界、旧浏览器回退和测试方法。只把 @media 改写成 @container,却没有建立容器或处理嵌套关系,代码无法按预期工作。

回答前需要澄清的问题

  • 响应什么尺寸? 本题响应卡片分配到的内联尺寸,不响应整个视口。
  • 是否需要样式或滚动状态查询? 本题只需要尺寸查询;样式查询和滚动状态查询属于可选扩展。
  • 兼容范围是什么? 先确认目标浏览器;不支持容器查询时保留可用的基础布局和媒体查询回退。
  • 组件边界是否嵌套? 若有嵌套卡片,使用 container-name 明确应该读取哪一层。

30 秒回答框架

“媒体查询观察视口,适合页面级断点;容器查询观察组件祖先容器,适合同一组件在不同布局槽位复用。先在卡片外层设置 container-type: inline-size,再用 @container 按容器内联尺寸切换布局。查询只影响后代,默认使用最近的合格容器;复杂嵌套用 container-name。我会提供基础样式和 @supports 回退,并在固定视口下调整父容器宽度测试主区、侧栏、网格和不支持该特性的浏览器。”

分步骤深入解答

第一步:先比较响应对象和作用域

维度媒体查询容器查询
响应对象视口、设备或用户偏好祖先查询容器的尺寸、样式或滚动状态
典型范围页面级布局可复用组件内部布局
建立方式@media 直接读取媒体特征祖先设置 container-type,后代使用 @container
组件行为同一视口通常共享断点每个实例可按实际分配宽度响应

媒体查询适合导航、整页栏列和打印等页面级决策。容器查询解决的是组件不知道自己会被放入多宽的槽位:主栏和侧栏可以在同一视口下分别采用不同布局。

第二步:建立尺寸查询上下文

css
.card-list {
  container-type: inline-size;
  container-name: card-list;
}

.card {
  display: grid;
  gap: 0.75rem;
}

@container card-list (inline-size > 40rem) {
  .card {
    grid-template-columns: 8rem 1fr;
    align-items: center;
  }
}

inline-size 建立按内联轴尺寸查询的容器,适合同时考虑不同书写模式的组件。size 会建立更强的双轴尺寸包含,只有在确实需要块轴查询时才使用。normal 不建立尺寸查询上下文。查询条件写在 @container 中,规则匹配容器的后代。

第三步:理解最近容器、命名和查询单位

未指定名称时,浏览器寻找最近的合格祖先;嵌套组件可能因此读取到错误边界。命名容器可以把意图写清楚:@container card-list (...) 只匹配名为 card-list 的容器。容器查询长度单位如 cqw、cqi 可按查询容器宽度或内联尺寸缩放,但仍应配合合理的最小值和最大值,避免小容器产生不可读文本。

查询规则不能让容器本身根据自己的查询结果改变尺寸,否则会形成反馈循环;规范通过包含和作用域限制避免这种循环。尺寸包含也可能改变自动尺寸计算,因此要检查空内容、图片未加载和高度依赖内容的情况。

第四步:设计回退和渐进增强

css
.card {
  display: block;
}

@supports (container-type: inline-size) {
  .card-list {
    container-type: inline-size;
  }

  @container (inline-size > 40rem) {
    .card {
      display: grid;
      grid-template-columns: 8rem 1fr;
    }
  }
}

基础布局应在没有容器查询时仍然可读。媒体查询可以作为页面级兜底,但不能假设视口断点能准确代表侧栏或网格单元宽度。若目标浏览器不支持 @supports 所检测的能力,就停留在基础样式,不影响核心内容和操作。

第五步:用场景和边界验证

固定浏览器视口,分别把同一组件放入主栏、侧栏和两列网格,再只调整父容器宽度,观察卡片是否按容器而非视口切换。测试嵌套命名容器、不同书写模式、图片加载前后、极窄容器、动态插槽和不支持容器查询的浏览器。还要确认组件没有依赖某个页面 DOM 层级,否则复用时会静默匹配到错误容器。

可接受的实现边界

回答不必覆盖所有查询类型,但必须准确区分视口与祖先容器,并让示例具备可运行的容器上下文。若选择 size、样式查询或滚动状态查询,应说明额外的包含影响、浏览器目标与测试边界;若不确定兼容范围,应明确把基础布局作为安全默认值。

常见错误与反例

  • 忘记设置 container-type:只有 @container 没有查询上下文,规则不会按尺寸生效。
  • 把容器写成自身查询目标:查询规则只能稳定地影响后代,不能用来让容器根据自己结果循环改变尺寸。
  • 把 size 当作默认值:双轴包含会影响自动尺寸,组件只关心横向时优先 inline-size。
  • 只在大屏测试:同一视口下侧栏和主栏宽度不同,必须固定视口并调整父容器验证。
  • 没有基础回退:旧浏览器中卡片可能失去布局,基础样式应先保证内容可用。

追问及应对

什么时候仍然使用媒体查询?

导航、整页栏列、打印和用户偏好等决策依赖视口或媒体特征时,媒体查询更直接。组件内部断点依赖父容器时,再使用容器查询。

inline-size 和 size 如何选择?

只按横向可用空间响应时选择 inline-size;需要同时按块轴和内联轴查询时才考虑 size,并验证自动尺寸、空内容和图片加载后的结果。

如何处理不支持容器查询的浏览器?

提供基础单列或流式布局,用 @supports (container-type: inline-size) 渐进增强;媒体查询可以补充页面级体验,但不能替代所有容器级断点。

公开来源

同类题目