Style by Parent Size, Not Just Viewport
Container & Container Queries
Use the container utility for centered max-widths, and v4's built-in container queries to style based on a parent's width.
What you'll learn
- Use the container utility with centering
- Mark a container and use its size variants
- Know when container queries beat breakpoints
Breakpoints answer “how big is the screen?” Container queries answer “how big is this element’s parent?” — and in v4 they need no plugin.
The container Utility
container sets a max-width that steps up at each breakpoint. Pair it with centering and padding for the standard page wrapper:
<div class="container mx-auto px-4">
<!-- page content, centered with sane gutters -->
</div> This is layout based on the viewport. Useful, but it knows nothing about where a component actually sits.
Container Queries
Mark an ancestor as a query container with @container, then style children with @-prefixed variants based on that container’s width:
<div class="@container">
<article class="flex flex-col @md:flex-row gap-4">
<img class="@md:w-1/3" src="/cover.jpg" alt="" />
<div class="@md:w-2/3">
<h3 class="text-base @lg:text-xl">Card title</h3>
</div>
</article>
</div> The card stacks when its container is narrow and goes side-by-side once the container (not the window) passes the @md size.
Why This Matters
Drop that same card into a wide main column and a narrow sidebar. With breakpoints it would behave identically in both because the screen is unchanged — wrong in the sidebar. With container queries it adapts to the space it is actually given, so a component is genuinely reusable anywhere.
You can name containers to query a specific ancestor:
<aside class="@container/sidebar">
<nav class="@sm/sidebar:flex">…</nav>
</aside> @sm/sidebar: responds only to the element named sidebar, even with other containers nested around it.