Skip to main content

Container Queries

Container queries are one of the most significant additions to CSS in recent years. They let you style elements based on the size of their container rather than the viewport. This changes how you think about responsive components.

The Problem with Media Queries

Media queries respond to the viewport width. This works for page-level layouts, but breaks down for reusable components:

/* This card needs to be compact in a sidebar but wide in the main area */
@media (min-width: 768px) {
  .card { display: flex; }
}

The media query does not know where the card lives. If the card is in a narrow sidebar on a wide screen, it still gets the wide layout. Media queries answer "how wide is the screen?" but components need to ask "how wide is my container?"

Container Query Syntax

To use container queries, you need two things: a containment context and a container query.

Step 1: Define the Container

.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

The container-type: inline-size property establishes the element as a query container for its inline dimension (width in horizontal writing modes). The container-name is optional but helps with clarity when you have multiple containers.

Shorthand syntax combines both:

.card-wrapper {
  container: card / inline-size;
}

Step 2: Write the Query

@container card (min-width: 400px) {
  .card {
    display: flex;
    gap: 1.5rem;
  }

  .card-image {
    width: 200px;
    flex-shrink: 0;
  }
}

@container card (min-width: 600px) {
  .card {
    padding: 2rem;
  }

  .card-title {
    font-size: 1.5rem;
  }
}

Now the card adapts based on how much space its wrapper has — whether that is in a sidebar, a grid cell, or a full-width section.

A Complete Example

<div class="grid">
  <div class="card-wrapper">
    <article class="card">
      <img class="card-image" src="/photo.jpg" alt="Project screenshot" />
      <div class="card-content">
        <h3 class="card-title">Project Update</h3>
        <p>The dashboard redesign is complete.</p>
      </div>
    </article>
  </div>
</div>
.card-wrapper {
  container: card / inline-size;
}

/* Default: stacked layout */
.card {
  display: grid;
  gap: 1rem;
}

.card-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 0.5rem;
}

/* When container is wide enough: horizontal layout */
@container card (min-width: 500px) {
  .card {
    grid-template-columns: 200px 1fr;
    align-items: start;
  }

  .card-image {
    aspect-ratio: 1;
  }
}

Place this card in a single-column layout and it stacks. Place it in a three-column grid and it stacks. Place it in a two-column grid with wide columns and it goes horizontal. The component itself decides — no external media queries needed.

Container vs Media Queries

FeatureMedia QueriesContainer Queries
Responds toViewport sizeParent container size
Best forPage layoutsReusable components
NestingNo concept of nestingQueries nearest container ancestor
Browser supportUniversalModern browsers (Chrome 105+, Firefox 110+, Safari 16+)

Use media queries for page-level layout decisions: how many columns in the grid, when to show the sidebar, when to switch navigation. Use container queries for component-level decisions: card layout, widget arrangement, content density.

Container Query Units

Container queries also introduce new units relative to the container size:

UnitMeaning
cqw1% of the container's width
cqh1% of the container's height
cqi1% of the container's inline size
cqb1% of the container's block size
@container (min-width: 300px) {
  .card-title {
    font-size: clamp(1rem, 4cqi, 1.75rem);
  }
}

This makes typography fluid relative to the container, not the viewport.

Practical Tips

  • Always use inline-size, not size. The size containment type restricts both axes and prevents the element from sizing based on its content height, which often breaks layouts.
  • Name your containers to avoid ambiguity when nesting multiple containers.
  • Combine with media queries for the best results. Use media queries for the overall page structure and container queries for components within that structure.
  • Provide a sensible default outside the @container block. The base styles should work even in the smallest container.