Apply CSS container queries for component-based responsive design. Use when implementing responsive components that adapt to their container size rather than viewport size.
Apply CSS container queries for component-based responsive design. Use when implementing responsive components that adapt to their container size rather than viewport size.
CSS Container Queries
A guide for implementing container-based responsive design using CSS container queries
and Tailwind CSS.
What
What are Container Queries?
Container queries enable styling elements based on their container's size rather than the
viewport size.
Unlike media queries that respond to the browser window,
container queries make components self-contained and truly reusable.
<!-- Define a container --><divclass="@container"><!-- Query the container --><divclass="@lg:grid-cols-2"><!-- Content adapts to container, not viewport -->
</div>
</div>
Container Query vs Media Query
Feature
Media Query
Container Query
Responds to
Viewport size
Container size
Reusability
Layout-dependent
Fully portable
Use case
Page layouts
Component styling
Syntax
@media
@container
Why
💡 Why Use Container Queries?
1.Component Portability
Components adapt to their context, not the viewport
Same component works in sidebar (narrow) or main area (wide)
No need for different component variants
2.Simpler Component Logic
Components don't need to know about page layout
Follows single responsibility principle
Reduces coupling between components and layouts
3.Better for Design Systems
Components are truly self-contained
Works in any layout context (grid, flex, sidebar)
Easier to maintain and test in isolation
4.Modern Web Architecture
Aligns with component-based frameworks (React, Vue, Svelte)
<divclass="@container"><!-- This is now a container context --></div>
Step 2: Use container query variants
<divclass="@container"><divclass="grid @lg:grid-cols-2 @xl:grid-cols-3"><!-- Responds to container size, not viewport --></div></div>
Available Tailwind Container Breakpoints:
@3xs - @container (width >= 16rem) (256px)
@2xs - @container (width >= 18rem) (288px)
@xs - @container (width >= 20rem) (320px)
@sm - @container (width >= 24rem) (384px)
@md - @container (width >= 28rem) (448px)
@lg - @container (width >= 32rem) (512px)
@xl - @container (width >= 36rem) (576px)
@2xl - @container (width >= 42rem) (672px)
@3xl - @container (width >= 48rem) (768px)
@4xl - @container (width >= 56rem) (896px)
@5xl - @container (width >= 64rem) (1024px)
@6xl - @container (width >= 72rem) (1152px)
@7xl - @container (width >= 80rem) (1280px)
📝 Note: These are Tailwind's default breakpoints.
You can customize them in globals.css (Tailwind v4) using CSS variables
or use arbitrary values like @min-[500px]:grid for custom container widths.
Step 3: Named containers (Tailwind)
<!-- Define named container --><divclass="@container/main"><!-- Query specific container --><divclass="@lg/main:grid-cols-3"><!-- Content --></div></div>
<!-- Tailwind: Reusable card adapts to any container --><divclass="@container"><articleclass="p-4 @md:p-6 @lg:flex @lg:gap-6"><imgclass="w-full @lg:w-64 rounded"src="card.jpg"alt="" /><div><h2class="text-lg @md:text-xl @lg:text-2xl font-bold">
Card Title
</h2><pclass="text-sm @md:text-base @lg:text-lg">
Card description that adapts to container width.
</p><buttonclass="mt-4 @md:mt-6">Action</button></div></article></div>
Why it's good: Card is self-contained and works in any layout context.
❌ Bad: Using Media Queries for Component Internals
<!-- Tailwind: Component depends on viewport, not container --><articleclass="p-4 md:p-6 lg:flex lg:gap-6"><imgclass="w-full lg:w-64 rounded"src="card.jpg"alt="" /><div><h2class="text-lg md:text-xl lg:text-2xl font-bold">
Card Title
</h2></div></article>
Why it's bad: Card assumes it's always full width at md breakpoint.
Breaks when placed in a sidebar.
✅ Good: Named Containers for Clarity
<!-- Tailwind: Multiple containers with clear names --><divclass="@container/sidebar"><navclass="@lg/sidebar:grid-cols-1"><!-- Sidebar navigation --></nav></div><divclass="@container/main"><divclass="@lg/main:grid-cols-3"><!-- Main content grid --></div></div>
Why it's good: Clear which container each query refers to.
Common Mistakes
❌ Mistake 1: Using container queries for page layouts
<!-- Don't do this --><bodyclass="@container"><mainclass="@lg:grid @lg:grid-cols-3">
Fix: Use media queries for page-level layouts.
❌ Mistake 2: Forgetting to define the container
<!-- Don't do this --><div><divclass="@lg:grid-cols-2"><!-- Won't work! --></div></div>
Fix: Always add @container to the parent.
❌ Mistake 3: Fixed heights with responsive content
/* Don't do this */.container {
height: 400px; /* Fixed height */
}
@container (min-width: 600px) {
.content {
columns: 2; /* Text will overflow! */
}
}
Fix: Use min-height or let content determine height.
❌ Mistake 4: Too many nested containers
<!-- Don't do this --><divclass="@container"><divclass="@container"><divclass="@container"><divclass="@lg:..."><!-- Confusing! --></div></div></div></div>
Fix: Use named containers and keep nesting shallow.