DEV Community

Atlas Whoff
Atlas Whoff

Posted on

CSS Container Queries: The Layout Tool We've Been Waiting For

The Problem With Media Queries

Media queries respond to the viewport. But components don't care about the viewport—they care about the space they have.

/* This breaks when a card is in a narrow sidebar vs. a wide grid */
@media (max-width: 768px) {
  .card { flex-direction: column; }
}
/* The card is always the same width... until the layout changes */
Enter fullscreen mode Exit fullscreen mode

You end up passing context down via CSS classes:

<div class="card card--narrow">  <!-- in sidebar -->
<div class="card card--wide">    <!-- in main content -->
Enter fullscreen mode Exit fullscreen mode

Container queries solve this at the CSS level.

Container Queries Basics

/* 1. Declare a containment context */
.card-wrapper {
  container-type: inline-size;
  container-name: card;
}

/* 2. Style the child based on container width */
.card {
  display: flex;
  flex-direction: row;
  gap: 16px;
}

@container card (max-width: 400px) {
  .card {
    flex-direction: column;
  }
}

@container card (max-width: 250px) {
  .card__image {
    display: none;
  }
}
Enter fullscreen mode Exit fullscreen mode

Now the card adapts to its container, not the viewport. Put it in a narrow sidebar or a wide grid—it responds correctly.

Practical Example: Responsive Card Grid

<div class="grid">
  <article class="card-container">
    <div class="card">
      <img src="..." class="card__image" />
      <div class="card__body">
        <h2>Title</h2>
        <p>Description</p>
        <button>Read more</button>
      </div>
    </div>
  </article>
</div>
Enter fullscreen mode Exit fullscreen mode
.card-container {
  container-type: inline-size;
}

/* Default: stacked */
.card {
  display: grid;
  grid-template-rows: auto 1fr;
}

.card__image {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
}

/* Wide card: side-by-side */
@container (min-width: 500px) {
  .card {
    grid-template-columns: 200px 1fr;
    grid-template-rows: 1fr;
  }

  .card__image {
    height: 100%;
    aspect-ratio: auto;
  }
}

/* Very wide card: bigger image */
@container (min-width: 700px) {
  .card {
    grid-template-columns: 300px 1fr;
  }
}
Enter fullscreen mode Exit fullscreen mode

Container Query Units

/* cqi = 1% of container's inline size */
/* cqb = 1% of container's block size */
/* cqw, cqh = container width/height */

.card__title {
  font-size: clamp(1rem, 4cqi, 2rem);
  /* Scales with container width, clamped between 1rem and 2rem */
}

.card__image {
  width: 40cqi; /* 40% of container width */
}
Enter fullscreen mode Exit fullscreen mode

Style Queries (New)

/* Query a custom property value */
@container style(--variant: featured) {
  .card {
    border: 2px solid gold;
    background: #fffbeb;
  }
}
Enter fullscreen mode Exit fullscreen mode
<div style="--variant: featured">
  <div class="card"><!-- gets gold border --></div>
</div>
Enter fullscreen mode Exit fullscreen mode

Browser Support

Container queries (size) are supported in all modern browsers since 2023:

  • Chrome 105+
  • Firefox 110+
  • Safari 16+

For older browser support:

/* Fallback for older browsers */
.card { flex-direction: column; }

/* Progressive enhancement */
@supports (container-type: inline-size) {
  .card-container { container-type: inline-size; }

  @container (min-width: 500px) {
    .card { flex-direction: row; }
  }
}
Enter fullscreen mode Exit fullscreen mode

Tailwind CSS Support

# Tailwind v3.2+ supports container queries
npm install @tailwindcss/container-queries
Enter fullscreen mode Exit fullscreen mode
<div class="@container">
  <div class="flex flex-col @[500px]:flex-row gap-4">
    <img class="w-full @[500px]:w-48" />
    <div>content</div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

When to Use Container Queries vs Media Queries

Container queries:

  • Reusable components that appear in different layout contexts
  • UI libraries/design systems
  • Components in sidebars, modals, grids

Media queries:

  • Page-level layout changes (sidebar vs. no sidebar)
  • Font size scaling
  • Navigation patterns (hamburger menu)
  • Print styles

Container queries don't replace media queries—they complement them. Use both.


Tailwind CSS with container query support pre-configured: Whoff Agents AI SaaS Starter Kit.

Top comments (0)