prefer-container-queries

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Prefer 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
md:flex-row
will get that wrong every time. Container queries fix this: the component asks "how wide am I?" instead of "how wide is the window?".
When 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:
here means "when the container is at least 28rem wide", regardless of viewport size. This card works in a sidebar, a modal, and a full-width grid without changing a single class.
Two rules that trip people up:
  1. The
    @container
    class goes on the parent. The
    @md:
    variants go on descendants. An element cannot query its own size.
  2. Container variants respond to the nearest ancestor with
    @container
    . If styles are not applying, check which container you are actually querying.
将父元素标记为容器,然后在其子元素上使用带
@
前缀的变体:
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:
表示“当容器宽度至少为28rem时”,与视口大小无关。无论放在侧边栏、模态框还是全宽网格中,这个卡片无需修改任何类就能正常工作。
容易让人出错的两条规则:
  1. @container
    类要添加在父元素上。
    @md:
    变体要添加在后代元素上。元素无法查询自身的尺寸。
  2. 容器变体响应的是最近的带有
    @container
    的祖先元素。如果样式未生效,请检查实际查询的是哪个容器。

Variants

变体

Tailwind v4 ships container queries in core. The sizes:
VariantMin width
@3xs
16rem (256px)
@2xs
18rem (288px)
@xs
20rem (320px)
@sm
24rem (384px)
@md
28rem (448px)
@lg
32rem (512px)
@xl
36rem (576px)
@2xl
42rem (672px)
@3xl
48rem (768px)
@4xl
56rem (896px)
@5xl
64rem (1024px)
@6xl
72rem (1152px)
@7xl
80rem (1280px)
Also available:
  • @max-md:
    styles below a container size.
  • @min-[475px]:
    arbitrary values when the scale does not fit.
  • @container/sidebar
    plus
    @md/sidebar:flex-row
    to name a container and query it from deeper in the tree, past other containers.
The full docs for this can be found here.
On Tailwind v3, the same syntax needs the
@tailwindcss/container-queries
plugin. Check the Tailwind version before writing classes.
Tailwind v4的核心功能中包含容器查询。尺寸对应关系如下:
变体最小宽度
@3xs
16rem(256px)
@2xs
18rem(288px)
@xs
20rem(320px)
@sm
24rem(384px)
@md
28rem(448px)
@lg
32rem(512px)
@xl
36rem(576px)
@2xl
42rem(672px)
@3xl
48rem(768px)
@4xl
56rem(896px)
@5xl
64rem(1024px)
@6xl
72rem(1152px)
@7xl
80rem(1280px)
此外还有:
  • @max-md:
    :容器尺寸小于指定值时生效的样式。
  • @min-[475px]:
    :当预设尺寸不适用时,可使用任意自定义值。
  • @container/sidebar
    搭配
    @md/sidebar:flex-row
    :可为容器命名,并从DOM树中更深的位置(跨越其他容器)查询该容器。
完整文档可查看此处
在Tailwind v3中,相同语法需要使用
@tailwindcss/container-queries
插件。编写类之前请先检查Tailwind版本。

When 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

迁移现有代码

  1. Find the component's responsive classes (
    sm:
    ,
    md:
    ,
    lg:
    ).
  2. Add
    @container
    to the component's root or the wrapper that owns the available space.
  3. Replace viewport variants with the container variant that matches the actual width where the layout should change. Do not map
    md:
    to
    @md:
    blindly;
    md
    is 768px of viewport,
    @md
    is 448px of container. Resize the container, not the window, to find the real breakpoint.
  4. Test the component in its narrowest real context (sidebar, drawer, small grid cell), not just at mobile viewport widths.
  1. 找到组件中的响应式类(
    sm:
    md:
    lg:
    )。
  2. 在组件的根元素或拥有可用空间的包裹元素上添加
    @container
  3. 将视口变体替换为与布局实际应变化的宽度匹配的容器变体。不要盲目地将
    md:
    映射到
    @md:
    md
    对应视口宽度768px,
    @md
    对应容器宽度448px。调整容器大小(而非窗口大小)来找到真正的断点。
  4. 在组件最狭窄的实际使用场景(侧边栏、抽屉、小网格单元)中进行测试,而不只是在移动端视口宽度下测试。

Mistakes to catch in review

评审时需注意的错误

  • md:flex-row
    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:
    variants used with no
    @container
    ancestor. They silently never apply.
  • @container
    and a
    @md:
    variant on the same element. The element cannot query itself; move the variant to a child or the container class to the parent.
  • 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:
    变体。元素无法查询自身;请将变体移至子元素,或将容器类移至父元素。
  • 仅在构建时的特定位置显示正常的组件。如果将其移至不同列就会失效,说明它与视口绑定了。