Container Queries

Introduction

Media queries adapt layouts based on viewport size, but components are often rendered inside containers of very different widths. A card in a narrow sidebar should not look the same as the same card in a wide main content area. This chapter introduces container queries, which let components respond to their own container size instead of only the global viewport.

Prerequisites

  • Responsive design fundamentals
  • Media queries and breakpoints
  • Basic Flexbox/Grid component layout knowledge

Why Container Queries

Media queries answer:

  • "How wide is the viewport?"

Container queries answer:

  • "How wide is this component's container?"

This is crucial for reusable components in:

  • sidebars
  • cards inside different page regions
  • dashboard widgets
  • embedded modules in CMS layouts

The same component can adapt locally without page-level breakpoint coupling.

Core Setup: Declaring a Query Container

Before using @container, mark a parent as a container.

css
.card-shell {
  container-type: inline-size;
}

Code explanation:

  • container-type: inline-size enables size queries based on container width in writing direction
  • descendants can now use @container rules referencing this container
  • this keeps component responsiveness local and reusable

Basic Container Query Syntax

css
.product-card {
  display: grid;
  gap: 0.75rem;
}
 
@container (min-width: 480px) {
  .product-card {
    grid-template-columns: 120px 1fr;
    align-items: start;
  }
}

Code explanation:

  • base style is mobile/compact by default
  • when container width reaches 480px, card switches to two-column layout
  • behavior depends on parent container width, not viewport width

Naming Containers

You can give containers explicit names for clarity in larger layouts.

css
.card-shell {
  container-type: inline-size;
  container-name: card;
}
 
@container card (min-width: 480px) {
  .product-card {
    grid-template-columns: 120px 1fr;
  }
}

Code explanation:

  • container-name: card labels this query context
  • @container card (...) targets that named container
  • helps avoid ambiguity when nested containers exist

Container Queries vs Media Queries

Use media queries when:

  • whole page structure changes by viewport
  • global nav/header/footer behavior changes

Use container queries when:

  • component layout depends on available local space
  • same component appears in multiple host contexts

In real projects, they usually work together.

Practical Pattern: Adaptive Card Component

Result:

  • narrow shell -> stacked avatar + text
  • wider shell -> horizontal avatar + text layout

Same component, smarter local adaptation.

Practical Pattern: Widget Density Tuning

This pattern is excellent for dashboards where widget widths vary by panel placement.

Nested Layouts and Scoped Responsiveness

Container queries reduce global breakpoint complexity in nested UIs:

  • page layout can stay viewport-driven
  • each component can self-adjust internally

This avoids writing many page-specific override selectors like:

  • .sidebar .card ...
  • .main .card ...

Component CSS becomes more portable and maintainable.

Container Query Units (Quick Note)

You may also see container-relative units:

  • cqw, cqh, cqi, cqb, cqmin, cqmax

Example:

css
.title {
  font-size: clamp(1rem, 3cqi, 1.5rem);
}

These are useful but not required for getting started. Begin with @container conditions first.

Progressive Enhancement and Fallback

Not all environments may fully support every modern feature combination.

Safe strategy:

  1. write a solid base layout first
  2. enhance with container queries
  3. optionally guard advanced behavior with feature checks

Example:

css
@supports (container-type: inline-size) {
  .card-shell {
    container-type: inline-size;
  }
}

Even without container query support, base layout should remain usable.

Tip

Base First, Enhance Second

Treat container queries as enhancement, not a requirement for core readability and interaction.

Common Mistakes

MistakeWhy it hurtsBetter approach
Forgetting to set container-typeQueries never triggerDefine container context explicitly
Using only viewport queries for reusable componentsExcessive context-specific overridesMove local adaptation to container queries
Over-querying tiny style tweaksUnnecessary complexityUse container queries for meaningful structural shifts
No base style before query blocksPoor fallback behaviorBuild robust default first
Ambiguous nested containersHard debuggingUse container-name in complex structures

Debugging Container Queries

If a query does not apply:

  1. verify ancestor has container-type
  2. inspect actual container width in DevTools
  3. check if threshold condition is met
  4. confirm selector and cascade order
  5. test by temporarily lowering threshold

When debugging, focus on container size, not viewport size.

Mini Exercise

  1. Create a reusable card component inside two different wrappers (narrow and wide)
  2. Add container-type: inline-size on each wrapper
  3. Write one @container (min-width: 500px) rule to switch card layout
  4. Compare behavior in both wrappers at same viewport width
  5. Add a named container version and verify it still works

FAQ

Are container queries replacing media queries?

No. They solve different scopes. Media queries are viewport-level; container queries are component-level.

Why is my container query never firing?

Most common reason: missing container-type on an ancestor container.

Should every component use container queries?

Not necessarily. Use them where components appear in varying container sizes and need local adaptation.

Is container-name required?

No. It is optional but helpful in complex or nested query contexts.

Can I combine media and container queries together?

Yes, and that is often ideal: global structure with media queries, local component behavior with container queries.