CSS Superpower: Unlocking the Magic of Container Queries

Components that respond to the space they sit in rather than the viewport, and the one declaration people forget to add.

csstutoriallayoutbeginner

I hit this on a dashboard where the same card appeared in a narrow sidebar, a two-column main area, and a full-width settings page. Media queries couldn't help. The card only knew the window was 1400px wide, so in a 240px sidebar it still rendered a 2rem title across two lines. I shipped a wrapper div and a resize observer instead.

Container queries let a component ask about the box it sits in rather than the window.

What are Container Queries?

A media query asks how big the viewport is. A container query asks how big this element's parent is.

You opt a parent in as a container, then query it:

.card {
    container-type: inline-size;
}
 
@container (min-width: 400px) {
    .card-title {
        font-size: 2rem;
    }
}

The container-type: inline-size line is the part I forget. Without it the @container block silently does nothing.

What Changes

  • Components respond to their own space, so one card can work in a sidebar and in a wide column without knowing which it's in.
  • Design system components stop needing props like isNarrow, passed down from a page that happens to know the layout.
  • You can drop the wrapper divs and JS resize listeners you may have added to fake this.

Widgets and sidebars can rearrange themselves when they run out of room.

Where I Use Them

  • Reusable UI components: buttons, cards, or widgets that need to work in more than one layout.
  • Dynamic grids: items that reflow when a column narrows, which happens constantly once users start dragging the window.
  • Complex layouts: sidebars and tool panels where font size or orientation should follow the panel width.

Real-World Example

A product card that stacks when it's cramped and goes horizontal when it has room:

.product-card {
    container-type: inline-size;
    display: flex;
    flex-direction: column;
}
 
@container (min-width: 600px) {
    .product-card {
        flex-direction: row;
    }
    .product-image {
        width: 300px;
    }
}

In a tight sidebar it stacks. On a roomy page the image moves to the side. Same markup, same CSS.

Beyond Width

Width is the common case, but @container can query height and other container features too. Support is good enough now that I reach for container queries first when styling a component in isolation.


If one of your components keeps breaking in a narrow column, that's the one to convert first.