先记住这个答案
写成 @media (...) { @container (...) { ... } } 即可,内层样式只有两个条件都成立时才生效。比如桌面视口足够宽,同时某张卡片自身也足够宽,才显示卡片的双栏信息。@media 和 @container 测量的不是同一个对象,不能把两个宽度数字简单合并成一个条件。
- 嵌套两种查询表示条件同时满足
@media看视口或设备特征@container看祖先容器- 命中后仍遵循 CSS 层叠
宽视口里仍可能有窄组件
大屏页面的侧栏只有很窄的一列。如果仅用 @media (min-width: 60rem),侧栏里的卡片也会切成双栏,文字很快挤坏。加容器条件后,只有实际分到足够宽度的卡片才切换。
.card { container-type: inline-size; }
@media (min-width: 60rem) {
@container (min-width: 30rem) {
.card__details { display: grid; grid-template-columns: 1fr 1fr; }
}
}大屏窄侧栏满足外层媒体查询,却不满足内层容器查询,所以仍保持单栏。要注意 .card__details 必须是 .card 的后代,卡片本身不能用自己的宽度查询自身。
若没有全局大屏限制的业务理由,单独使用容器查询通常就够了。两层条件适合确实需要同时依赖页面环境和组件宽度的场景。
命中后还要看层叠
查询只是决定某条 CSS 规则是否参与层叠。即使两个条件都为真,后面权重更高或层级更靠后的声明仍可能覆盖它。调试时先看查询是否命中,再查选择器权重和样式顺序。
如果需要“满足 A 或 B”,不能把嵌套当成或关系。应该分写规则或使用相应查询语法;嵌套自然表示两道门都通过。
实际项目里,两个条件可以表示不同职责:媒体查询判断用户是否有宽屏工作区,容器查询判断某个预览面板是否真有放两列详情的空间。用户把侧栏拖宽时,视口不变,只有容器条件可能从假变真;缩小整个窗口时,即使面板还够宽,外层条件也可能让双栏退回。先把这两种变化分别测试,才能确认嵌套是产品要求,而非多加一道限制。
容易答错的地方
- 把两个宽度当成同一个数
- 媒体条件通常基于视口,容器条件基于选定祖先。视口宽不代表组件宽。
- 忘了创建尺寸容器
- 没有合格的
container-type,内层尺寸查询无法按预期命中,即使外层媒体查询已经成立。
面试官还会怎么问?
可以把 @media 写在 @container 里面吗?
可以。两个嵌套条件都成立才生效;为了便于阅读,通常先放影响范围更大的页面条件。
为什么桌面侧栏卡片没有双栏?
先检查卡片实际宽度是否达到容器断点,再检查查询目标是否是卡片后代和容器类型是否正确。
只需要根据组件宽度变化时还要加媒体查询吗?
一般不需要。单独的容器查询更容易让组件在不同页面、弹窗和侧栏中复用。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。