Container Queries
In this chapter, you learn about container queries, which gained native support in Tailwind CSS v4.
What are container queries
Container queries are a feature that applies styles based on the size of the parent container rather than the viewport.
<!-- Traditional media query: depends on the viewport width -->
<div class="md:flex">...</div>
<!-- Container query: depends on the container width -->
<div class="@container">
<div class="@md:flex">...</div>
</div>
Basic usage
Defining a container
Define a container with the @container class.
<div class="@container">
<div class="@md:flex @lg:grid @lg:grid-cols-2">
A layout that responds to the container size
</div>
</div>
Container breakpoints
| Prefix | Min 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) |
<div class="@container">
<div class="block @sm:flex @lg:grid @lg:grid-cols-3">
A responsive layout
</div>
</div>
Named containers
You can give containers names to distinguish between multiple ones.
<div class="@container/main">
<div class="@container/sidebar">
<div class="@lg/main:flex @md/sidebar:block">
Reference named containers
</div>
</div>
</div>
@max-* variants
With the @max-* variants, you can apply styles when the container width is below a specified value.
<div class="@container">
<div class="flex flex-row @max-md:flex-col">
Stacked vertically when the container width is below 448px (28rem)
</div>
</div>
By stacking it with a regular variant, as in @sm:@max-md:flex, you can also specify a range.
Arbitrary values
<div class="@container">
<div class="@[500px]:flex">
flex at 500px and up
</div>
</div>
Container queries vs media queries
The problem with media queries
<!-- Media query: with a sidebar, cards go side by side even when narrow -->
<div class="grid grid-cols-1 md:grid-cols-2">
<Card />
<Card />
</div>
The container query solution
<!-- Container query: change the layout based on the card's own width -->
<div class="@container">
<div class="block @md:flex gap-4">
<Card />
<Card />
</div>
</div>
Practical examples
Responsive card
<article class="@container bg-white rounded-xl shadow-lg overflow-hidden">
<div class="@md:flex">
<!-- Image -->
<div class="@md:w-1/3 @lg:w-1/4">
<img
src="..."
class="w-full h-48 @md:h-full object-cover"
/>
</div>
<!-- Content -->
<div class="p-6 @md:w-2/3 @lg:w-3/4">
<span class="text-sm text-blue-600 font-semibold">Category</span>
<h2 class="mt-2 text-xl @lg:text-2xl font-bold">Title</h2>
<p class="mt-2 text-gray-600 @lg:text-lg">
The description goes here...
</p>
<div class="mt-4 flex flex-col @sm:flex-row gap-2">
<button class="px-4 py-2 bg-blue-500 text-white rounded-sm">
Details
</button>
<button class="px-4 py-2 border border-gray-300 rounded-sm">
Save
</button>
</div>
</div>
</div>
</article>
Dashboard widget
<div class="@container bg-white rounded-lg shadow-sm p-4">
<div class="@xs:flex @xs:justify-between @xs:items-center mb-4">
<h3 class="font-bold text-lg">Sales statistics</h3>
<span class="text-sm text-gray-500">Last 30 days</span>
</div>
<div class="grid grid-cols-1 @sm:grid-cols-2 @lg:grid-cols-4 gap-4">
<div class="p-4 bg-blue-50 rounded-lg">
<p class="text-sm text-blue-600">Total sales</p>
<p class="text-2xl font-bold">¥1,234,567</p>
</div>
<div class="p-4 bg-green-50 rounded-lg">
<p class="text-sm text-green-600">Orders</p>
<p class="text-2xl font-bold">1,234</p>
</div>
<div class="p-4 bg-yellow-50 rounded-lg">
<p class="text-sm text-yellow-600">Average price</p>
<p class="text-2xl font-bold">¥12,345</p>
</div>
<div class="p-4 bg-purple-50 rounded-lg">
<p class="text-sm text-purple-600">Repeat rate</p>
<p class="text-2xl font-bold">45.6%</p>
</div>
</div>
</div>
Sidebar + main content
<div class="flex">
<!-- Sidebar -->
<aside class="w-64 shrink-0">
<nav class="p-4">Sidebar</nav>
</aside>
<!-- Main content (uses container queries) -->
<main class="flex-1 @container p-4">
<div class="grid grid-cols-1 @md:grid-cols-2 @xl:grid-cols-3 gap-6">
<!-- Card -->
<div class="@container bg-white rounded-lg shadow-sm">
<div class="@xs:flex p-4">
<img src="..." class="w-full @xs:w-20 h-20 object-cover rounded-sm" />
<div class="mt-2 @xs:mt-0 @xs:ml-4">
<h3 class="font-bold">Title</h3>
<p class="text-sm text-gray-600">Description...</p>
</div>
</div>
</div>
<!-- Repeat -->
</div>
</main>
</div>
Product card
<div class="@container group bg-white rounded-xl shadow-lg overflow-hidden">
<!-- Image section -->
<div class="relative @lg:flex">
<div class="@lg:w-1/2">
<img
src="..."
class="w-full aspect-square @lg:aspect-auto @lg:h-full object-cover"
/>
</div>
<!-- Details section -->
<div class="p-6 @lg:w-1/2 @lg:flex @lg:flex-col @lg:justify-center">
<div class="flex items-center gap-2 mb-2">
<span class="px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded-full">
New
</span>
<span class="text-sm text-gray-500">SKU: 12345</span>
</div>
<h2 class="text-xl @md:text-2xl font-bold">
Product name
</h2>
<p class="mt-2 text-gray-600 @md:text-lg line-clamp-3 @lg:line-clamp-none">
The detailed product description goes here. Long text is
clamped in small containers.
</p>
<div class="mt-4 @sm:flex @sm:items-center @sm:justify-between">
<div>
<span class="text-2xl font-bold text-blue-600">¥12,800</span>
<span class="ml-2 text-sm text-gray-400 line-through">¥15,800</span>
</div>
<button class="mt-4 @sm:mt-0 w-full @sm:w-auto px-6 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg">
Add to cart
</button>
</div>
</div>
</div>
</div>
Search result item
<div class="@container">
<article class="@md:flex gap-4 p-4 bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow">
<!-- Thumbnail -->
<div class="@md:w-48 @md:shrink-0">
<img
src="..."
class="w-full h-48 @md:h-32 object-cover rounded-sm"
/>
</div>
<!-- Content -->
<div class="mt-4 @md:mt-0 flex-1">
<div class="@lg:flex @lg:justify-between @lg:items-start">
<div>
<h3 class="font-bold text-lg hover:text-blue-600">
Search result title
</h3>
<p class="mt-1 text-sm text-gray-500">
Posted by: Username • 3 hours ago
</p>
</div>
<div class="mt-2 @lg:mt-0 flex gap-2">
<span class="px-2 py-1 bg-gray-100 text-gray-600 text-xs rounded-sm">
Tag 1
</span>
<span class="px-2 py-1 bg-gray-100 text-gray-600 text-xs rounded-sm">
Tag 2
</span>
</div>
</div>
<p class="mt-2 text-gray-600 line-clamp-2 @lg:line-clamp-3">
The search result description goes here...
</p>
<div class="mt-4 flex items-center gap-4 text-sm text-gray-500">
<span>👍 123</span>
<span>💬 45</span>
<span>👁 1.2k</span>
</div>
</div>
</article>
</div>
Container query best practices
1. Make components self-contained
<!-- Good: define the container inside the component -->
<div class="@container">
<div class="@md:flex">...</div>
</div>
<!-- Avoid: depending on the parent -->
<div class="md:flex">...</div>
2. Choose appropriate breakpoints
<!-- Breakpoints matched to the component's size -->
<div class="@container max-w-md">
<div class="@xs:flex">For a small container</div>
</div>
<div class="@container max-w-4xl">
<div class="@lg:grid @lg:grid-cols-3">For a large container</div>
</div>
3. Be careful with nesting
<!-- Be explicit with named containers -->
<div class="@container/outer">
<div class="@container/inner">
<div class="@md/outer:flex @sm/inner:block">
An explicit reference
</div>
</div>
</div>
Summary
- Define a container with
@container - Use
@sm:/@md:/@lg:, etc. for styles that respond to the container size - Specify upper bounds with
@max-*variants such as@max-md: - Distinguish between multiple containers with named containers
- Ideal for component-based development
- Can be combined with media queries
What to read next
- Animations — add motion with
transition/animate-* - Component patterns — Tailwind implementations of practical UI parts
- Tailwind CSS Guide table of contents — back to the structure of all 18 chapters