CSS Container Queries: The Complete Guide for 2026

February 11, 2026

For over a decade, media queries were the only way to build responsive layouts in CSS. They work well for page-level decisions like switching a two-column layout to a single column on small screens. But they have a fundamental limitation: they respond to the viewport, not to the component's actual available space. A card component has no way to know whether it is sitting in a 300px sidebar or a 900px main content area. Container queries solve this problem entirely.

This guide covers everything you need to know about CSS container queries in 2026: the core syntax, container-type and container-name properties, size queries and style queries, container query units, nesting containers, real-world responsive component patterns, when to use container queries versus media queries, browser support, performance considerations, and a practical migration strategy from media queries to container queries.

⚙ Build it: Create responsive layouts visually with our CSS Grid Generator, test responsive breakpoints with the CSS Media Query Builder, or experiment with flexible layouts in the Flexbox Generator.

The Problem: Media Queries Are Page-Level, Not Component-Level

Consider a card component that needs to display vertically when narrow and horizontally when wide. With media queries, you write something like this:

/* Media query approach: tied to the viewport */
.card {
    display: flex;
    flex-direction: column;
}

@media (min-width: 768px) {
    .card {
        flex-direction: row;
    }
}

This works when the card is full-width. But what happens when you place the same card in a narrow sidebar on a wide desktop screen? The viewport is 1200px, so the media query triggers the horizontal layout, but the sidebar is only 300px wide. The card renders horizontally in a 300px space and looks broken. You end up writing sidebar-specific overrides, and the component is no longer reusable.

Container queries eliminate this problem. Instead of asking "how wide is the viewport?", the component asks "how wide is my container?" The same card adapts correctly in every context without any overrides.

What Are Container Queries?

Container queries let you apply CSS styles to an element based on the size (or style properties) of its nearest containment context — a parent element that has been designated as a container. The key shift is from viewport-relative responsiveness to container-relative responsiveness.

There are two parts to using container queries:

  1. Define a container — set container-type on a parent element to establish a containment context.
  2. Query the container — use @container rules to apply styles based on the container's dimensions or custom properties.
/* Step 1: Define the container */
.card-wrapper {
    container-type: inline-size;
}

/* Step 2: Query the container */
.card {
    display: flex;
    flex-direction: column;
    padding: 1rem;
}

@container (min-width: 450px) {
    .card {
        flex-direction: row;
        gap: 1.5rem;
    }
}

Now the card switches to horizontal layout when its container is at least 450px wide, regardless of the viewport size. Place it in a sidebar, a modal, a grid cell, or a full-width section — it always responds to its actual available space.

The container-type Property

The container-type property establishes an element as a query container. It accepts three values:

/* inline-size: containment on the inline axis only (width) */
/* This is the value you will use 95% of the time */
.wrapper {
    container-type: inline-size;
}

/* size: containment on both inline and block axes (width + height) */
/* Requires the container to have an explicit height */
.fixed-panel {
    container-type: size;
    height: 400px;
}

/* normal: no containment (default, cannot be queried) */
.wrapper {
    container-type: normal;
}

Use inline-size as your default choice. It enables width-based queries without requiring an explicit height on the container. The size value tracks both width and height, which is useful for fixed-dimension panels like dashboard widgets, but the container must have an explicit height set, otherwise it may collapse to zero.

Important: setting container-type establishes CSS containment on the element. This means the container cannot depend on its children for sizing in the contained axis. In practice, this is rarely an issue because containers are usually wrapper elements whose width is determined by the layout, not by their content.

The container-name Property

When you have multiple nested containers, you can name them to target a specific one in your queries:

/* Name containers individually */
.page-layout {
    container-type: inline-size;
    container-name: layout;
}

.sidebar {
    container-type: inline-size;
    container-name: sidebar;
}

.main-content {
    container-type: inline-size;
    container-name: main;
}

/* Query a specific container by name */
@container sidebar (min-width: 300px) {
    .sidebar-widget {
        display: grid;
        grid-template-columns: 1fr 1fr;
    }
}

@container main (min-width: 700px) {
    .article-card {
        flex-direction: row;
    }
}

There is also a shorthand container property that sets both name and type:

/* Shorthand: container: <name> / <type> */
.sidebar {
    container: sidebar / inline-size;
}

/* Equivalent to: */
.sidebar {
    container-type: inline-size;
    container-name: sidebar;
}

Without a name, @container queries match the nearest ancestor that has container-type set. Naming is only necessary when you need to skip over a closer container to query one further up the tree.

The @container Syntax

The @container at-rule works like @media, but queries the container instead of the viewport:

/* Basic size query */
@container (min-width: 500px) {
    .component { /* styles */ }
}

/* Named container query */
@container card-area (min-width: 400px) {
    .card { /* styles */ }
}

/* Range syntax (same as media queries level 4) */
@container (width >= 600px) {
    .component { /* styles */ }
}

@container (300px <= width < 600px) {
    .component { /* medium layout */ }
}

/* Combining conditions */
@container (min-width: 500px) and (min-height: 300px) {
    .panel { /* both conditions must be true */ }
}

Size Queries: inline-size, block-size, width, height

Size queries are the most common type of container query. You can query these dimensions:

/* Width-based queries (require container-type: inline-size or size) */
@container (min-width: 400px) { ... }
@container (max-width: 599px) { ... }
@container (width >= 400px) { ... }
@container (400px <= width < 800px) { ... }

/* Logical equivalents */
@container (min-inline-size: 400px) { ... }
@container (inline-size >= 400px) { ... }

/* Height-based queries (require container-type: size) */
@container (min-height: 300px) { ... }
@container (height >= 300px) { ... }
@container (min-block-size: 300px) { ... }

/* Aspect ratio */
@container (aspect-ratio > 1) {
    /* Container is wider than it is tall */
}

/* Orientation */
@container (orientation: landscape) {
    /* Container width exceeds its height */
}

In practice, you will use width-based queries almost exclusively. Height queries require container-type: size, which in turn requires an explicit height on the container. Reserve height queries for fixed-dimension contexts like dashboard widgets or split-pane editors.

Style Queries: @container style()

Style queries let you apply styles based on the computed value of CSS custom properties on a container. Instead of querying dimensions, you query the container's style:

/* Define a custom property on the container */
.card-wrapper {
    container-type: inline-size;
    --card-variant: default;
}

.card-wrapper.featured {
    --card-variant: featured;
}

.card-wrapper.compact {
    --card-variant: compact;
}

/* Query the custom property value */
@container style(--card-variant: featured) {
    .card {
        border: 2px solid var(--primary);
        background: rgba(59, 130, 246, 0.05);
    }
    .card-title {
        font-size: 1.5rem;
        color: var(--primary);
    }
}

@container style(--card-variant: compact) {
    .card {
        flex-direction: row;
        padding: 0.5rem;
        gap: 0.75rem;
    }
    .card-image {
        width: 60px;
        height: 60px;
        border-radius: 50%;
    }
}

Style queries are powerful for theming and variant systems. You set a custom property on a container, and all descendants respond automatically. No extra classes on every child element. Note that style queries currently work in Chrome 111+ and Edge 111+; Firefox and Safari support is still in development as of early 2026.

Container Query Units

Container queries introduce six new length units relative to the container's dimensions:

/* Container query units reference:
   cqw   = 1% of container width
   cqh   = 1% of container height
   cqi   = 1% of container inline size
   cqb   = 1% of container block size
   cqmin = smaller of cqi and cqb
   cqmax = larger of cqi and cqb */

/* Fluid typography relative to container width */
.card-title {
    font-size: clamp(1rem, 4cqi, 2rem);
}

/* Spacing that scales with the container */
.card-body {
    padding: clamp(0.75rem, 3cqi, 2rem);
}

/* Image sizing relative to container */
.card-image {
    height: clamp(120px, 30cqi, 300px);
}

/* Responsive icon size */
.widget-icon {
    width: clamp(24px, 8cqi, 48px);
    height: clamp(24px, 8cqi, 48px);
}

Container query units are especially useful inside clamp() for fluid scaling. They work like viewport units (vw, vh) but are scoped to the container, making them perfect for component-level fluid design. They resolve against the nearest ancestor with container-type set.

Nesting Containers

You can nest containers freely. Each @container query resolves against the nearest matching container ancestor:

/* Outer container */
.page-layout {
    container: page / inline-size;
    display: grid;
    grid-template-columns: 1fr;
}

/* Inner container */
.content-area {
    container: content / inline-size;
}

/* This queries the nearest container (content-area) */
@container (min-width: 500px) {
    .article {
        columns: 2;
    }
}

/* This queries the named outer container */
@container page (min-width: 1024px) {
    .page-layout {
        grid-template-columns: 280px 1fr;
    }
}

/* This queries the named inner container */
@container content (min-width: 700px) {
    .article {
        columns: 3;
        column-gap: 2rem;
    }
}

When nesting, use named containers to be explicit about which container you are querying. Unnamed queries match the closest ancestor container, which can lead to unexpected results if you add a new container in between.

Real-World Patterns

Pattern 1: Responsive Card Component

/* The wrapper is the container */
.card-wrapper {
    container-type: inline-size;
}

/* Default: vertical stack (narrow contexts) */
.card {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    overflow: hidden;
}

.card-img {
    width: 100%;
    height: 180px;
    object-fit: cover;
}

.card-body { padding: 1rem; }
.card-title { font-size: 1.1rem; font-weight: 600; }

/* Medium: horizontal layout */
@container (min-width: 450px) {
    .card { flex-direction: row; }
    .card-img {
        width: 200px;
        height: auto;
        min-height: 160px;
    }
}

/* Wide: featured style with larger text */
@container (min-width: 700px) {
    .card-img { width: 320px; }
    .card-title { font-size: 1.5rem; }
    .card-body { padding: 1.5rem; }
}

Pattern 2: Adaptive Sidebar Navigation

.sidebar {
    container: sidebar / inline-size;
}

/* Narrow sidebar: icon-only nav */
.nav-item {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.75rem;
    border-radius: 6px;
}

.nav-label { display: none; }

.nav-icon {
    width: 24px;
    height: 24px;
    flex-shrink: 0;
}

/* Wide sidebar: icons + labels */
@container sidebar (min-width: 200px) {
    .nav-item {
        justify-content: flex-start;
        gap: 0.75rem;
        padding: 0.75rem 1rem;
    }
    .nav-label {
        display: block;
        white-space: nowrap;
    }
}

/* Extra wide: add descriptions */
@container sidebar (min-width: 300px) {
    .nav-description {
        display: block;
        font-size: 0.8rem;
        color: var(--text-muted);
    }
}

Pattern 3: Dashboard Widget

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

.widget {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 8px;
    padding: 1rem;
}

.widget-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1rem;
}

.widget-stat {
    font-size: clamp(1.5rem, 6cqi, 3rem);
    font-weight: 700;
}

/* Small widget: stack stat and chart */
.widget-content {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* Medium widget: side by side */
@container widget (min-width: 400px) {
    .widget-content {
        flex-direction: row;
        align-items: center;
    }
    .widget-chart {
        flex: 1;
        min-height: 120px;
    }
}

/* Large widget: more detail */
@container widget (min-width: 600px) {
    .widget { padding: 1.5rem; }
    .widget-details { display: block; }
    .widget-table { display: table; }
}

Pattern 4: Responsive Navigation Bar

.nav-container {
    container: topnav / inline-size;
}

/* Narrow: hamburger menu */
.nav-links { display: none; }
.menu-toggle { display: flex; }

/* Medium: priority links visible */
@container topnav (min-width: 500px) {
    .menu-toggle { display: none; }
    .nav-links {
        display: flex;
        gap: 0.5rem;
    }
    .nav-links .secondary { display: none; }
}

/* Wide: all links + CTA visible */
@container topnav (min-width: 800px) {
    .nav-links .secondary { display: flex; }
    .nav-cta {
        display: inline-flex;
        margin-left: auto;
    }
}
⚙ Try it: Build these layout patterns visually with our CSS Grid Generator and Flexbox Generator. See our CSS Flexbox Cheat Sheet for quick property references.

Container Queries vs Media Queries: When to Use Each

Container queries do not replace media queries. Each serves a different purpose, and the best responsive designs use both.

Use media queries for:

Use container queries for:

/* Typical approach: combine both */

/* Media query: page-level layout */
@media (min-width: 1024px) {
    .page {
        display: grid;
        grid-template-columns: 300px 1fr;
    }
    .sidebar { display: block; }
}

/* Container query: component-level adaptation */
.card-wrapper { container-type: inline-size; }

@container (min-width: 450px) {
    .card { flex-direction: row; }
}

/* Media query: user preferences */
@media (prefers-color-scheme: dark) {
    :root { --bg: #0f1117; }
}

@media (prefers-reduced-motion: reduce) {
    * { transition-duration: 0.01ms !important; }
}

Browser Support and Progressive Enhancement

As of February 2026, container query support is excellent:

For progressive enhancement, use @supports to detect container query support:

/* Fallback: media query for older browsers */
@media (min-width: 768px) {
    .card {
        flex-direction: row;
    }
}

/* Enhancement: container query for modern browsers */
@supports (container-type: inline-size) {
    .card-wrapper {
        container-type: inline-size;
    }

    /* Override the media query with container query */
    .card {
        flex-direction: column; /* Reset to default */
    }

    @container (min-width: 450px) {
        .card {
            flex-direction: row;
        }
    }
}

This approach ensures older browsers get a reasonable media-query-based responsive layout, while modern browsers get the superior container-query-based one.

Performance Considerations

Container queries are well optimized in modern browsers, but there are a few things to keep in mind:

/* GOOD: Container on the wrapper, not every element */
.widget-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 1rem;
}

.widget-wrapper {
    container-type: inline-size;
}

/* BAD: Unnecessary containers everywhere */
.widget-grid { container-type: inline-size; }   /* Not needed */
.widget-wrapper { container-type: inline-size; } /* This one is needed */
.widget { container-type: inline-size; }         /* Not needed */
.widget-body { container-type: inline-size; }    /* Not needed */

Migration Strategy from Media Queries

You do not need to rewrite your entire CSS to adopt container queries. Here is a practical step-by-step migration strategy:

Step 1: Identify candidates. Look for components that appear in multiple layout contexts. Cards, widgets, navigation components, and form elements that live in both sidebars and main content areas are the best candidates.

Step 2: Add containers to wrappers. Add container-type: inline-size to the parent wrappers of those components. This has no visual effect on its own.

Step 3: Convert media queries to container queries. For each candidate component, change @media (min-width: ...) to @container (min-width: ...). Adjust the breakpoint values — container widths are typically smaller than viewport widths.

Step 4: Keep media queries for page layout. Continue using @media for page-level grid changes, sidebar visibility, and user preferences.

/* BEFORE: Everything uses media queries */
.card { flex-direction: column; }

@media (min-width: 768px) {
    .card { flex-direction: row; }
    .sidebar { display: block; width: 300px; }
}

/* AFTER: Mixed approach */
/* Page layout: still media queries */
@media (min-width: 1024px) {
    .page { grid-template-columns: 300px 1fr; }
    .sidebar { display: block; }
}

/* Component layout: container queries */
.card-wrapper { container-type: inline-size; }

.card { flex-direction: column; }

@container (min-width: 450px) {
    .card { flex-direction: row; }
}

Step 5: Test in every context. Resize the browser, toggle sidebars, and check every place the component appears. Container queries change the component's behavior in ways that viewport-based testing alone will not reveal.

Frequently Asked Questions

What is the difference between container queries and media queries?

Media queries respond to the viewport (browser window) size, while container queries respond to the size of a parent container element. Media queries use @media and are ideal for page-level layout changes like switching column counts. Container queries use @container and let components adapt based on the space they actually occupy. A card in a 300px sidebar behaves differently from the same card in a 900px content area, automatically. Use media queries for page layout and user preferences; use container queries for reusable components.

What is the difference between container-type inline-size and size?

container-type: inline-size enables containment on the inline axis only (width in horizontal writing modes). This is the default choice for almost all use cases. container-type: size enables containment on both width and height, but requires the container to have an explicit height set. Without one, the container may collapse. Only use size when you need height-based container queries, such as for fixed-dimension dashboard widgets or vertically scrolling panels.

What are container query units like cqw and cqi?

Container query units are relative lengths based on the nearest container ancestor. cqw = 1% of container width, cqh = 1% of container height, cqi = 1% of container inline size, cqb = 1% of container block size, cqmin = smaller of cqi and cqb, cqmax = larger. They work like viewport units but scoped to the container, making them ideal for fluid typography: font-size: clamp(1rem, 4cqi, 2rem) scales text based on available container space.

Do CSS container queries work in all browsers?

Size container queries are supported in Chrome 105+, Firefox 110+, Safari 16+, and Edge 105+ — over 95% global coverage in 2026. Style queries (@container style()) are more limited: Chrome 111+ and Edge 111+ only, with Firefox and Safari still developing support. For older browsers, use @supports (container-type: inline-size) to provide a media-query fallback alongside container query enhancements.

How do I migrate from media queries to container queries?

Migrate incrementally. Identify components that appear in multiple layout contexts (cards, widgets, navigation). Add container-type: inline-size to their parent wrappers. Convert each component's @media rules to @container rules, adjusting breakpoint values since container widths are smaller than viewport widths. Keep media queries for page-level layout and user preferences. Use @supports to provide fallbacks for older browsers. Test in every context where the component appears.

Summary

Container queries are the most significant advancement in CSS layout since Flexbox and Grid. They solve a problem that media queries structurally cannot: making components responsive to their own context rather than the viewport. Here are the key takeaways:

  1. Use container-type: inline-size on wrapper elements to create containment contexts. This is the only value you need in most cases.
  2. Use @container queries for components that appear in multiple layout contexts: cards, widgets, navigation, and any reusable UI element.
  3. Keep @media queries for page-level layout, user preferences (dark mode, reduced motion), and device capabilities (hover, pointer).
  4. Use container query units (cqi, cqw) with clamp() for fluid typography and spacing inside components.
  5. Name your containers with container-name when nesting to be explicit about which container you are querying.
  6. Use @supports for progressive enhancement so older browsers fall back to media queries gracefully.
  7. Migrate incrementally — start with your most reused components and work outward.

For more on responsive CSS layout, read our CSS Grid Complete Guide, CSS Flexbox Complete Guide, and CSS Media Queries Complete Guide. For quick property references, keep our CSS Flexbox Cheat Sheet bookmarked.

Related Resources

CSS Grid Complete Guide
Master CSS Grid for two-dimensional layouts
CSS Flexbox Complete Guide
Master CSS Flexbox for one-dimensional layouts
CSS Media Queries Complete Guide
Viewport-level responsive design with media queries
CSS Media Query Builder
Build and test responsive breakpoints visually
CSS Flexbox Cheat Sheet
Quick reference for all Flexbox properties