Viewport breakpoints are still useful, but they answer the wrong question for many components. A card, sidebar, or pricing module often needs to react to the space it has, not the size of the browser. Container queries let the parent define that space.

Tip: Reach for container queries when a component can appear in more than one layout context: grid, rail, modal, or dashboard panel.

Start with containment

Mark the parent as a query container. Then write rules against the parent width instead of the viewport width.

.card-shell { container-type: inline-size; }
@container (min-width: 36rem) {
  .card { grid-template-columns: 14rem 1fr; }
}

This keeps the component portable. The same card can be narrow in a sidebar and wide in a content grid without adding modifier classes.

Parent width → query condition → component layout 24rem: stacked 36rem: media + content columns 52rem: add metadata rail

Use them for component contracts

A clean pattern is to define a small set of layout states. Avoid recreating your whole breakpoint system inside every component. Name the states in comments, document the expected ranges, and keep tokens shared.

Container queries are not a replacement for responsive design. They are the missing layer between global page layout and component behavior. Use viewport breakpoints for the page shell; use container queries for reusable modules.