🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.
CSS MASTER CLASS /// VISUAL ENGINEERING /// LAYOUT DESIGN /// ANIMATION LAB /// CSS MASTER CLASS /// VISUAL ENGINEERING ///

Container Queries: Responsive Design At The Component Level

Learn how to declare a containment context with container-type, write @container rules that respond to it, and use container query units for component-relative fluid sizing.

Total XP: 0|💻 css XP: 0

Skill Matrix

UNLOCK NODES BY LEARNING NEW TAGS.

Container Queries

Component-relative responsive design.


🚀 LEVEL UP TO SENIOR:Unlock 500+ Advanced Practical Challenges & Exercises.
🎓 COURSERA PARTNER:Earn professional Google, Meta, and IBM certificates to supercharge your resume.

Media queries answer 'how big is the viewport'. Container queries answer the question components actually need answered: 'how much space do I have right now, wherever I happen to be placed'.

1Why Viewport-Based Responsiveness Falls Short For Components

A media query only ever knows one thing: the browser viewport's size. That's the right signal for page-level layout decisions (should the sidebar collapse), but it's the wrong signal for a reusable component, which might be rendered in a 300px sidebar widget or a 900px main content area on the very same page, at the very same viewport width.

Before container queries, working around this meant either giving up on true component reusability (hardcoding different markup per placement) or resorting to JavaScript-measured ResizeObserver hacks just to fake what should be a CSS-native capability.

/* Media query: only knows viewport width */
@media (min-width: 768px) { .card { } }
localhost:3000
⚠ Blind To PlacementThis rule fires identically whether .card sits in a 300px sidebar or a 900px column — it can't tell them apart.

2Declaring And Querying A Container

Two steps are required. First, an ancestor opts in with container-type: inline-size (tracking width) or size (tracking both axes, with layout implications). Optionally add container-name to target that specific container by name when nested containers exist. Second, descendants use @container with the same condition syntax as @mediamin-width, max-width, aspect-ratio — but evaluated against the nearest matching container instead of the viewport.

A subtlety worth internalizing: container-type establishes a new containment context, which has a real, if usually minor, layout implication — the container becomes a query boundary its own size can't query against (to prevent circular dependencies).

.sidebar { container-type: inline-size; }

@container (min-width: 400px) {
  .card { grid-template-columns: 120px 1fr; }
}
localhost:3000
✓ Context-AwareThe .card layout now genuinely depends on its container's real width, not the browser window's.

3Container Units For Fluid, Component-Relative Scaling

Beyond conditional rules, container queries add a family of relative units mirroring viewport units: cqw/cqh (1% of container width/height), cqi/cqb (1% of container inline/block size), and cqmin/cqmax (the smaller/larger of the two). Combined with clamp(), these produce component-scoped fluid typography that scales smoothly with the container's actual size rather than jumping at fixed breakpoints.

This matters most for design systems: a single .card__title rule can now scale correctly whether the card is rendered small in a grid or large in a hero layout, without any conditional rule needing to be written at all.

.card__title {
  font-size: clamp(16px, 5cqi, 28px);
}
localhost:3000
Container width 320px → ~16px title
Container width 800px → ~28px title
No breakpoint rules needed

4Step-by-Step Breakdown

Responsive To The Container, Not The Screen. Media queries respond to the viewport — but a component doesn't know or care how big the browser window is; it cares how much space its own container gives it. Container Queries close that gap, letting a card render its 'narrow' layout in a 300px sidebar and its 'wide' layout in a 900px main column, on the exact same page, at the exact same viewport size.

Declaring A Containment Context. Before an element's children can query its size, the element itself must opt in via container-type. Setting container-type: inline-size tells the browser to track that element's inline-axis size and expose it to descendant @container rules — nothing is queryable by default.

Establishing A Container. What CSS property must an ancestor element declare before its descendants can use @container queries against its size?

  • container-type
  • position
  • display

Querying With @container. Once a containment context exists, descendants use @container exactly like @media, but measuring the nearest named ancestor container instead of the viewport. The same card component can now define genuinely different layouts based purely on the space it's actually given.

Container Query Syntax. A .card inside a 320px-wide sidebar and the same .card inside a 900px-wide main column both exist on one page at one viewport width. Can they render differently using @container?

  • No — media queries would be required for that
  • Yes — each container query evaluates against its own nearest container's actual size
  • Only on mobile viewports

Container Query Units: cqw, cqh, cqi. Alongside conditional rules, container queries introduce container-relative units — cqw (1% of container width), cqi (1% of container inline-size), and others — letting values like font-size scale fluidly relative to the container's size rather than the viewport's.

Container Query Units. What does 5cqi mean when used inside a container context?

  • 5% of the viewport width, same as 5vw
  • 5% of the nearest container's inline-size
  • 5% of the root html element's font-size

Component Responsiveness Unlocked. You now know how to opt an element into a containment context, write @container rules that respond to that context's actual size, and use container-relative units for fluid, component-scoped sizing. This is the feature that finally makes 'truly reusable responsive components' possible in CSS.

Declare A Query Container. container-type: inline-size opts an element into being a query container for its children's container queries.

Level Up 🚀

Advanced cheat sheets, SEO tricks, and interview prep for this topic.

Browser Support

ChromeSupported

Fully supported.

FirefoxSupported

Fully supported.

SafariSupported

Fully supported.

EdgeSupported

Fully supported.

Accessibility (A11y)

1Container-Relative Typography Must Still Respect User Zoom And Text-Size Preferences

Pairing cqi units with clamp()'s pixel-based min/max bounds can override a user's browser text-size preference; prefer rem-based bounds inside clamp() so container-driven scaling still respects accessibility zoom settings.

2Container Queries Don't Change Focus Order, But Layout Shifts They Trigger Can Disorient Keyboard Users

When a container query drastically reorders a component's visual layout at certain sizes, verify the underlying DOM order (and therefore tab order) still makes logical sense at every container width.

SEO Implications

  • 1

    Container Queries Reduce Duplicate Component Variants, Shrinking Total CSS Payload

    Before container queries, teams often shipped separate 'compact' and 'full' component variants to handle different placements; a single container-queried component can replace both, reducing the CSS bundle.

  • 2

    True Component Reusability Improves Development Velocity On Content-Heavy Sites

    Faster, more reliable component reuse across different page templates indirectly supports faster iteration on content structure, which correlates with better crawl and indexing efficiency for large sites.

Best Practices

Default To container-type: inline-size Unless You Specifically Need Block-Axis Queries

inline-size avoids the layout containment side effects of size containment, which forces the container to lay out as if empty until its content is measured — a subtlety that can introduce visual flicker if misapplied.

Name Containers Explicitly Once You Have More Than One Nested Containment Context

Without container-name, an @container rule matches the nearest ancestor container of any kind, which becomes ambiguous and error-prone once containers are nested inside other containers.

Frequent Bugs

THE BUG

An @container rule never seems to match, even though the container is clearly wide enough.

THE FIX

The ancestor element is missing container-type entirely — @container rules only evaluate against elements that have explicitly opted into a containment context.

THE BUG

A component briefly flashes with incorrect sizing before settling into its correct container-queried layout.

THE FIX

container-type: size was used instead of inline-size, forcing the browser to lay out the container as empty first. Switch to inline-size unless block-axis containment is genuinely required.

Real-World Examples

A Card That Adapts To Sidebar vs Main Column

A single .card component used both in a 300px sidebar and a 900px main content area, rendering a compact stacked layout in the former and a horizontal layout in the latter.

.layout-region { container-type: inline-size; }
@container (min-width: 500px) {
  .card { display: grid; grid-template-columns: 140px 1fr; }
}

Interview Prep

?Frequently Asked Questions

Pascual Vila

Pascual Vila

Frontend Instructor // Code Syllabus

Common Pitfalls & Errors

The Error //

Writing @container rules without declaring container-type on an ancestor

/* Wrong: no containment context declared */ @container (min-width: 400px) { .card { } } /* Correct */ .wrapper { container-type: inline-size; } @container (min-width: 400px) { .card { } }

The Solution //

Add container-type: inline-size (or size) to the intended ancestor before any descendant @container rule can match.

The Error //

Using container-type: size when only width needs to be tracked

/* Usually correct default */ .wrapper { container-type: inline-size; }

The Solution //

Prefer inline-size to avoid unnecessary layout containment side effects and potential flicker.

Lesson Glossary

[01]Container Query

A CSS rule that responds to an ancestor container's size.

Code Preview
@container

[02]container-type

The property that opts an element into a queryable containment context.

Code Preview
inline-size

[03]container-name

An optional name for targeting a specific container by @container rules.

Code Preview
container-name: card

[04]Container Query Unit

A unit relative to the nearest container's size (cqw, cqi, etc).

Code Preview
5cqi

Continue Learning