prefer-container-queries
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePrefer Container Queries
优先使用容器查询
Components should respond to the space they are in, not to the viewport. A card that lives in a sidebar has maybe 300px of width even on a huge screen, and a viewport breakpoint like will get that wrong every time. Container queries fix this: the component asks "how wide am I?" instead of "how wide is the window?".
md:flex-rowWhen writing responsive Tailwind, default to container queries. Viewport breakpoints are the exception, not the rule.
组件应根据自身所在的空间而非视口做出响应。即使在超大屏幕上,侧边栏中的卡片宽度可能也只有300px,而像这样的视口断点每次都会判断错误。容器查询解决了这个问题:组件会询问“我自身的宽度是多少?”而非“窗口的宽度是多少?”。
md:flex-row编写响应式Tailwind代码时,默认使用容器查询。视口断点是例外情况,而非常规做法。
How it works
工作原理
Mark the parent as a container, then use -prefixed variants on its children:
@html
<div class="@container">
<div class="flex flex-col @md:flex-row @md:gap-6">
<img class="w-full @md:w-48" />
<div class="@md:flex-1">...</div>
</div>
</div>@md:Two rules that trip people up:
- The class goes on the parent. The
@containervariants go on descendants. An element cannot query its own size.@md: - Container variants respond to the nearest ancestor with . If styles are not applying, check which container you are actually querying.
@container
将父元素标记为容器,然后在其子元素上使用带前缀的变体:
@html
<div class="@container">
<div class="flex flex-col @md:flex-row @md:gap-6">
<img class="w-full @md:w-48" />
<div class="@md:flex-1">...</div>
</div>
</div>此处的表示“当容器宽度至少为28rem时”,与视口大小无关。无论放在侧边栏、模态框还是全宽网格中,这个卡片无需修改任何类就能正常工作。
@md:容易让人出错的两条规则:
- 类要添加在父元素上。
@container变体要添加在后代元素上。元素无法查询自身的尺寸。@md: - 容器变体响应的是最近的带有的祖先元素。如果样式未生效,请检查实际查询的是哪个容器。
@container
Variants
变体
Tailwind v4 ships container queries in core. The sizes:
| Variant | Min width |
|---|---|
| 16rem (256px) |
| 18rem (288px) |
| 20rem (320px) |
| 24rem (384px) |
| 28rem (448px) |
| 32rem (512px) |
| 36rem (576px) |
| 42rem (672px) |
| 48rem (768px) |
| 56rem (896px) |
| 64rem (1024px) |
| 72rem (1152px) |
| 80rem (1280px) |
Also available:
- styles below a container size.
@max-md: - arbitrary values when the scale does not fit.
@min-[475px]: - plus
@container/sidebarto name a container and query it from deeper in the tree, past other containers.@md/sidebar:flex-row
The full docs for this can be found here.
On Tailwind v3, the same syntax needs the plugin. Check the Tailwind version before writing classes.
@tailwindcss/container-queriesTailwind v4的核心功能中包含容器查询。尺寸对应关系如下:
| 变体 | 最小宽度 |
|---|---|
| 16rem(256px) |
| 18rem(288px) |
| 20rem(320px) |
| 24rem(384px) |
| 28rem(448px) |
| 32rem(512px) |
| 36rem(576px) |
| 42rem(672px) |
| 48rem(768px) |
| 56rem(896px) |
| 64rem(1024px) |
| 72rem(1152px) |
| 80rem(1280px) |
此外还有:
- :容器尺寸小于指定值时生效的样式。
@max-md: - :当预设尺寸不适用时,可使用任意自定义值。
@min-[475px]: - 搭配
@container/sidebar:可为容器命名,并从DOM树中更深的位置(跨越其他容器)查询该容器。@md/sidebar:flex-row
完整文档可查看此处。
在Tailwind v3中,相同语法需要使用插件。编写类之前请先检查Tailwind版本。
@tailwindcss/container-queriesWhen viewport breakpoints are still right
仍适合使用视口断点的场景
Do not convert these:
- Page-level layout. The overall grid, whether the sidebar exists at all, header and navigation behavior. These genuinely depend on the viewport.
- Fixed or sticky elements positioned relative to the viewport, like a bottom bar that becomes a side rail.
- Global typography scale tied to screen size.
Everything inside those layout regions, meaning cards, forms, media objects, stat blocks, table-to-list switches, should use container queries.
以下情况无需转换:
- 页面级布局。比如整体网格、侧边栏是否显示、页眉和导航的行为。这些确实取决于视口。
- 相对于视口定位的固定或粘性元素,比如从底部栏变为侧边栏的元素。
- 与屏幕尺寸绑定的全局排版比例。
而这些布局区域内的所有元素,比如卡片、表单、媒体对象、统计块、表格转列表的切换等,都应使用容器查询。
Migrating existing code
迁移现有代码
- Find the component's responsive classes (,
sm:,md:).lg: - Add to the component's root or the wrapper that owns the available space.
@container - Replace viewport variants with the container variant that matches the actual width where the layout should change. Do not map to
md:blindly;@md:is 768px of viewport,mdis 448px of container. Resize the container, not the window, to find the real breakpoint.@md - Test the component in its narrowest real context (sidebar, drawer, small grid cell), not just at mobile viewport widths.
- 找到组件中的响应式类(、
sm:、md:)。lg: - 在组件的根元素或拥有可用空间的包裹元素上添加。
@container - 将视口变体替换为与布局实际应变化的宽度匹配的容器变体。不要盲目地将映射到
md:;@md:对应视口宽度768px,md对应容器宽度448px。调整容器大小(而非窗口大小)来找到真正的断点。@md - 在组件最狭窄的实际使用场景(侧边栏、抽屉、小网格单元)中进行测试,而不只是在移动端视口宽度下测试。
Mistakes to catch in review
评审时需注意的错误
- on a component that is rendered inside a sidebar or modal. It will stay stacked or break depending on the viewport, not its actual space.
md:flex-row - variants used with no
@md:ancestor. They silently never apply.@container - and a
@containervariant on the same element. The element cannot query itself; move the variant to a child or the container class to the parent.@md: - A component that only looks right at the exact spot it was built for. If moving it to a different column breaks it, it is viewport-coupled.
- 在侧边栏或模态框内渲染的组件上使用。它会根据视口而非实际所在空间保持堆叠或布局错乱。
md:flex-row - 使用变体但没有
@md:祖先元素。这些变体将静默失效。@container - 在同一元素上同时使用和
@container变体。元素无法查询自身;请将变体移至子元素,或将容器类移至父元素。@md: - 仅在构建时的特定位置显示正常的组件。如果将其移至不同列就会失效,说明它与视口绑定了。