C

CSS Handbook

Clean • Professional

Container Queries in CSS (@container)

3 minute

Container Queries in CSS (@container)

Responsive design usually relies on media queries (@media), which adapt layouts based on the viewport size.

But sometimes, a component needs to adjust to its parent container, not the whole screen.

That’s where CSS Container Queries (@container) help. They let elements respond to their container’s size, making components modular, reusable, and flexible across different layouts.

Why Use Container Queries?

  • Component-friendly: Ideal for frameworks like React, Vue, and Angular.
  • Reusable layouts: Cards, widgets, and sidebars adapt anywhere.
  • Local control: Styles respond to the parent, not the screen.
  • Simpler CSS: Fewer breakpoints and overrides.
  • Future-ready: A smarter approach than traditional media queries.

Media Queries vs Container Queries

  • Media Queries → Media queries adapt layouts to the device.
  • Container Queries → Container queries adapt components to their parent container.

How to Use Container Queries

1: Define a Container

To enable container queries, you must declare a parent element as a query container:

container-type

  • inline-size → tracks the width only.
  • size → tracks both width and height.

container-name

  • Useful if you want to target a specific container in your query.
.container {
  container-type: inline-size; /* enables queries based on container width */
  container-name: card;        /* optional name for targeting */
}

2: Write a Container Query

  • Works like @media, but applies to the container, not the viewport.
  • If you use named containers, you can target them specifically:
@container (min-width: 40rem) {
  .component {
    display: flex;
    gap: 1rem;
  }
}
@container card (max-width: 500px) {
  .card {
    flex-direction: column;
  }
}

Example 1: Responsive Card Layout

The card stacks vertically in small containers and becomes a row layout in wider ones.

<div class="card-container">
  <div class="card">
    <img src="image.jpg" alt="Example">
    <p>This is a responsive card using container queries.</p>
  </div>
</div>
.card-container {
  container-type: inline-size;
  container-name: card;
  max-width: 600px;
  margin: auto;
}

.card {
  display: flex;
  flex-direction: row;
  gap: 1rem;
  padding: 1rem;
  border: 1px solid #ccc;
  background: #fff;
  border-radius: 10px;
}

/* Switch to vertical when container is narrow */
@container card (max-width: 400px) {
  .card {
    flex-direction: column;
    text-align: center;
  }
}

Example 2: Adaptive Sidebar Layout

The sidebar automatically stacks under the content if the parent container is too narrow.

<div class="layout">
  <aside class="sidebar">Sidebar</aside>
  <main class="content">Main Content</main>
</div>
.layout {
  display: flex;
  container-type: inline-size;
  gap: 1rem;
}

.sidebar {
  flex: 1;
  background: #ddd;
}

.content {
  flex: 3;
  background: #fff;
}

/* When container is narrow */
@container (max-width: 600px) {
  .layout {
    flex-direction: column;
  }
}

Example 3: Grid of Cards (Each Card Adapts Independently)

Each card responds based on its own width, not the overall grid or viewport.

<div class="grid">
  <div class="grid__item card">Card 1</div>
  <div class="grid__item card">Card 2</div>
  <div class="grid__item card">Card 3</div>
</div>
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1rem;
  padding: 1rem;
}

.grid__item {
  container-type: inline-size; /* each grid item acts as its own container */
}

.card {
  border: 1px solid #ccc;
  padding: 1rem;
  background: #fafafa;
}

/* Each card adapts individually */
@container (min-width: 28rem) {
  .card {
    display: flex;
    justify-content: space-between;
  }
}

 

Article 0 of 0