Skip to main content
Syllabus
On this page

Container Queries

Badar KhalilUpdated September 30, 2026 9 min read

CSS Container Queries: Component-Based Responsive Design

Focus keyword: CSS container queries. A media query asks how wide the screen is. A container query asks how wide the parent of a component is. That is a big difference for reusable components: the same card can be placed in a wide main area, a narrow sidebar or a modal, and it adapts to the space it really gets. In this lesson you will learn container-type, named containers, @container rules, container query units, style queries, the side effects of containment and how to combine container queries with media queries.

CSS container queries, @container rule, container-type inline-size, container-name, container shorthand, cqi cqw units, style queries, container style custom property, component-based responsive design, media queries vs container queries, reusable card component, container query range syntax, nested containers, size containment, layout containment, scroll-state container queries, container queries browser support, design system components.

1. The Problem with Media Queries

Media queries depend only on the viewport. If a product card switches to a horizontal layout at 700px viewport width, it will also switch when it is placed in a 250px wide sidebar on a large screen, where it does not fit. The designer has to write extra rules for every place where the card is used. Container queries move the decision into the component.

2. Defining a Container

Mark the parent element as a query container with container-type:

  • inline-size: the container can be queried by its inline size (width in horizontal writing). This is what you need in almost every case.
  • size: both width and height can be queried. It requires explicit sizes for both dimensions, because the container can no longer get its size from its content. Use it rarely.
  • normal: the default. The element is not a size container, but it can still be a style query container.

Give it a name with container-name: card, or use the shorthand container: card / inline-size. Names let a query target one specific container when several containers are nested.

3. Writing an @container Rule

@container (min-width: 400px) { .card { display: grid; grid-template-columns: 160px 1fr; } }. The rule applies to descendants of the container. An element cannot be styled by a query about its own size, so the container and the styled element must be different elements: a wrapper and the card inside it. Named version: @container card (min-width: 400px) { ... }. Without a name, the query uses the nearest ancestor that is a container of the right type.

Range syntax and conditions

You can use min-width, max-width, width, inline-size, block-size, height, aspect-ratio and orientation, and the range syntax: @container (300px <= width < 600px). Combine conditions with and, or and not.

4. Container Query Units

Inside a container you can size things relative to it:

  • cqw, cqh: 1 percent of the container width and height.
  • cqi, cqb: 1 percent of the container inline and block size. Prefer these logical units for writing-mode support.
  • cqmin, cqmax: the smaller or larger of cqi and cqb.

Use them with clamp() for fluid padding, gap and font size that follow the component: padding: clamp(0.75rem, 4cqi, 2rem). If there is no matching container, these units fall back to the small viewport units.

5. Style Queries

@container style(--theme: dark) { ... } applies styles when a container has a computed custom property with that value. It lets components change based on a state or a variant set by a parent, without adding classes to every child. Support is newer than size queries, so check browser support, use @supports when needed and keep a simple default. Newer additions such as scroll-state queries (for sticky, stuck and scrollable states) are emerging features, so treat them as progressive enhancement.

6. Side Effects of container-type

Setting container-type: inline-size applies containment to the element:

  • The container can no longer grow its width from its children. Give it a width from layout (block element, flex or grid item, or an explicit size).
  • It becomes a containing block for absolutely and fixed positioned descendants and creates a stacking context and a new formatting context, similar to contain: layout.
  • Margins of children do not collapse through it.
  • An inline element cannot be a size container. Use a block, flex, grid or inline-block element.

Because of this, do not turn every element into a container. Use containers where components need them, such as card wrappers, widgets and layout regions.

7. Container Queries with Nesting and Layers

Native CSS nesting works well with container queries. Put the @container block inside the component rule so all rules for that component stay together. You can also place it inside an @layer. Remember that a nested @container inside .card still queries an ancestor, not the card.

8. Container Queries vs Media Queries

  • Use media queries for page-level layout, such as the main grid and header, and for user preferences such as dark mode and reduced motion.
  • Use container queries for components that appear in different places, such as cards, pricing tables, widgets, form rows and media objects.
  • They work together: the page layout decides the width of each region, and the components adapt to that region.

9. Practical Patterns

  • Card layout: stacked below 400px, image left from 400px.
  • Navigation in a sidebar: icons only when narrow, icons and labels when wide.
  • Dashboard widget: hide secondary values in small tiles.
  • Grid items as containers: make each grid cell a container so the content adjusts to the cell, not to the screen.
  • Fluid typography inside components: use cqi with clamp.

10. Browser Support and Fallback

Size container queries have been supported in all current major browsers since 2023. For older browsers, write the mobile or default layout as the base styles, so the component still works, just without the wide layout. Use @supports (container-type: inline-size) if you need to give a different fallback.

11. Debugging

  • DevTools shows a container badge on elements with container-type, and you can inspect the matching queries.
  • If a query does nothing, check that the parent has container-type, that the styled element is a descendant and not the container itself, and that the container has a real width.
  • If the container collapses to zero width, it is probably an inline-level or shrink-to-fit element, so give it display block or a width.

12. Common Mistakes

  • Forgetting container-type, so the @container rule never matches.
  • Trying to style the container itself in its own query.
  • Making a shrink-to-fit element a size container and ending up with zero width.
  • Using container-type: size and not setting the height.
  • Making every element a container and creating unexpected stacking contexts.
  • Naming containers inconsistently and querying the wrong one.
  • Using container queries for page-level or preference decisions that belong to media queries.

Key Takeaways

Give the parent container-type: inline-size (and optionally a name), write @container rules for its descendants, use cqi units with clamp for fluid component sizes, know the containment side effects, keep media queries for page layout and preferences, and build a sensible base layout for browsers without support.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself HTML
Output

Press Run to execute.

Try it Yourself JAVASCRIPT
Output

Press Run to execute.

Exercise: Switch a Card Layout at 400pxHTML

Make .card-wrap a size container. Inside it, the card should be stacked by default and become a two column grid (140px image, flexible text) when the container is at least 400px wide. Use @container, not @media.

Try it Yourself HTML
Output

Press Run to execute.

Show expected output
The .card-wrap has container-type: inline-size and an @container (min-width: 400px) rule sets .card to grid-template-columns: 140px 1fr

This is a self-check — compare your result with the expected output above.

Exercise: Convert a Media Query Component to a Container QueryHTML

The same .promo component is used in a wide main area and a narrow sidebar, but the @media rule switches both at the same viewport width. Convert the component so it adapts to its own container: give each region a container name and replace the media query with an @container rule at 360px.

Try it Yourself HTML
Output

Press Run to execute.

Show expected output
.region has container-type: inline-size (optionally container: region / inline-size) and the media query is replaced by @container (min-width: 360px) so the narrow sidebar promo stays stacked

This is a self-check — compare your result with the expected output above.

Was this page helpful?