Tailwind Container Queries
Breakpoints such as md: respond to the width of the browser window. A component often lives in places of different widths: a wide main column on one page and a narrow sidebar on another. Container queries let the component respond to the width of its own parent, so one card design adapts everywhere.
The Problem With Window Breakpoints
Imagine a product card that switches to a side-by-side layout at md:. On a desktop the card sits in a narrow sidebar, and the side-by-side layout squeezes the text into a thin strip, even though the window is wide. The card needs to know the size of its own box, not the size of the window.
Window is wide (1200px) in both cases
Main column (700px) Sidebar (250px)
┌──────────────────────┐ ┌──────────┐
│ [img] Title │ │ [img] │
│ Description │ │ Title │
└──────────────────────┘ │ Descr. │
side-by-side fits well └──────────┘
stacked fits well
Marking a Container
Add the @container class to the parent. Children can then use variants that start with the at sign.
<div class="@container">
<div class="flex flex-col gap-4 @md:flex-row">
<img class="w-full @md:w-48" src="item.jpg" alt="Item photo">
<div>
<h4 class="font-bold">Product name</h4>
<p>Short description.</p>
</div>
</div>
</div>
The layout switches to a row once the container reaches the @md width, no matter how large the window is.
Container Size Names
Variant Minimum container width
────────────────────────────────────
@xs 320px (20rem)
@sm 384px (24rem)
@md 448px (28rem)
@lg 512px (32rem)
@xl 576px (36rem)
@2xl 672px (42rem)
Version 4 includes container queries in the core. Version 3 requires the official @tailwindcss/container-queries plugin.
Maximum Width and Ranges
Use @max-md: to apply a rule below a size. Stack a minimum and a maximum to target a band.
@max-md:hidden → hidden when the container is narrower than 448px
@sm:@max-lg:p-2 → applies between 384px and 512px
Named Containers
Nested containers need names so a child targets the right ancestor. Add a name after a slash.
<div class="@container/sidebar">
<p class="@md/sidebar:text-lg">Responds to the sidebar width</p>
</div>
Custom Sizes
Arbitrary values handle sizes outside the preset list.
@min-[400px]:flex-row → row layout at 400px and wider
@max-[300px]:text-sm → small text under 300px
Window Breakpoints Against Container Breakpoints
Question Use
──────────────────────────────────────────────────
Does the whole page layout change? md: lg: xl:
Does a reusable component adapt? @md: @lg:
Is the component placed in many spots? container queries
Is it a page-level header or footer? window breakpoints
Both tools work together. Page structure uses window breakpoints. Reusable parts use container queries.
Component Library Benefits
Design systems benefit most from container queries. A component built once can move between a dashboard, an article page, and a mobile layout without extra variants. Developers stop writing special versions such as "sidebar card" and "main card." Fewer variants mean fewer bugs and smaller code.
Testing becomes simpler too. Place the component in boxes of 250, 450, and 700 pixels wide on a test page and check each result. The window size no longer matters during that test.
A Layman Comparison
Think of a picture frame in a shop. A window breakpoint measures the size of the whole shop and picks one frame style for every picture. A container query measures each wall space and picks the frame that fits that exact spot. The picture adapts to the space it actually receives, which gives a better result in tight corners and wide walls alike.
The same thinking helps when you plan a layout. Ask where the component might appear in the future, not just where it appears today. A card used in a three-column grid today may move into a modal tomorrow. Container queries prepare it for both homes.
Browser Support and Fallbacks
Container queries work in current versions of Chrome, Edge, Safari, and Firefox. Visitors on older browsers see the default stacked layout, which stays usable because the base classes describe the smallest design. Mobile first writing protects those visitors automatically.
- Set the base layout without any prefix so every browser shows something sensible.
- Avoid placing a container query on the same element that carries the
@containerclass. The variant must live on a child. - Give the container a block or flex display with real width, because an inline element has no measurable size.
With container queries, each component carries its own responsive rules wherever it travels.
