容器查询@container必须先在父元素声明container-type: inline-size(或size)才生效,否则规则被忽略;字体缩放需用CSS变量配合断点修改,再通过font-size过渡实现平滑变化,且仅Chrome110+/Safari16.4+原生支持。

容器查询(@container)必须先定义容器尺寸阈值
直接写 @container 不生效,浏览器根本不会触发——因为 CSS 默认不把任意元素当作可查询的容器。必须显式给父元素加 container-type: inline-size(或 size),否则所有子元素里的 @container 规则都会被忽略。
常见错误是只写了查询规则,却忘了在包裹元素上声明容器类型:
.card {
container-type: inline-size; /* 缺了这行,下面的 @container 就是摆设 */
}注意:inline-size 基于内容流方向,对水平文档流就是宽度;若用 container-type: size,还需同时设 container-name 才能匹配命名查询。
字体大小不能直接在 @container 里用 calc() 动态算,得靠 CSS 变量中转
CSS 容器查询本身不支持基于容器宽高做实时数学运算(比如 font-size: calc(1rem + 0.25vw) 这种视口单位在容器查询里无效)。想实现“宽度越小、字号越小”的渐进缩放,得靠变量 + 查询断点组合:
立即学习“前端免费学习笔记(深入)”;
- 先在根或组件作用域定义一个变量,比如
--fs-base - 在不同
@container断点里修改该变量值 - 文本元素统一用
font-size: var(--fs-base)
示例:
.text-block {
--fs-base: 1.25rem;
font-size: var(--fs-base);
}
<p>@container (min-width: 400px) {
.text-block {
--fs-base: 1.5rem;
}
}</p><p>@container (min-width: 600px) {
.text-block {
--fs-base: 1.75rem;
}
}容器宽度变化时字体不会“平滑过渡”,需手动加 transition
容器查询本身不触发 CSS 过渡动画,font-size 变化默认是突变。如果希望字号随容器缩放缓慢调整,必须显式声明 transition,且目标属性要是变量所影响的最终属性(不是变量本身):
- ✅ 正确:给
font-size加transition: font-size 0.3s ease - ❌ 错误:试图给
--fs-base加 transition(CSS 变量不支持 transition)
另外注意:只有当容器尺寸因 DOM 变化(如 resize、flex 伸缩、JS 修改 width)而重排时,@container 才会重新计算。纯 CSS 动画或 transform 缩放不会触发容器查询更新。
兼容性差的现实:Chrome 110+ / Safari 16.4+ 才原生支持,Firefox 仍需前缀
目前 @container 在 Firefox 中尚未稳定支持,需用 @-moz-container(但行为不完全一致,且未来可能移除)。实际项目中若需兼容旧版浏览器,不能只依赖容器查询:
- 降级方案:用媒体查询(
@media)兜底,监听视口而非容器 - 更可靠方案:用 ResizeObserver + JS 动态设 CSS 变量,再由 CSS 消费(适合复杂响应逻辑)
- 构建时处理:PostCSS 插件如
postcss-container-query可将简单容器查询转为媒体查询,但丢失容器上下文语义
真正棘手的不是怎么写,而是判断「这个容器是否真的在运行时被测量」——很多情况下,父元素没设 container-type,或被 display: contents / overflow: hidden 等隐式禁用容器能力,调试时得一层层检查 computed styles 里的 container-type 是否生效。


















