Beyond Media Queries

Media queries respond to viewport size. Container queries respond to a parent container’s size — enabling truly reusable components that adapt to their context, not the screen.

A card in a narrow sidebar and a wide main column can use the same component with different layouts.

Enabling Container Queries

A parent must be a query container:

  .card-wrapper {
    container-type: inline-size;
    container-name: card;
}
  
Property Values Effect
container-type normal, size, inline-size Which dimensions to query
container-name custom name Named container for @container
container shorthand type + name combined

Use inline-size for most component layouts (width in horizontal writing mode).

Basic Container Query

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

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

    .card__image {
        width: 40%;
    }
}

@container (max-width: 399px) {
    .card {
        display: block;
    }

    .card__image {
        width: 100%;
    }
}
  
  <div class="card-container">
    <article class="card">...</article>
</div>
  

Named Containers

When nesting containers, name them to target specific ancestors:

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

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

@container sidebar (max-width: 250px) {
    .widget { font-size: 0.875rem; }
}

@container main (min-width: 600px) {
    .widget { display: grid; grid-template-columns: 1fr 1fr; }
}
  

Shorthand container

  .card-wrapper {
    container: card / inline-size;
    /* equivalent to:
       container-name: card;
       container-type: inline-size;
    */
}

@container card (min-width: 500px) { ... }
  

Container Query Units

Size-relative units based on container dimensions:

Unit Reference
cqw 1% of container width
cqh 1% of container height
cqi 1% of inline size
cqb 1% of block size
cqmin smaller of cqi/cqb
cqmax larger of cqi/cqb
  @container (min-width: 300px) {
    .card__title {
        font-size: clamp(1rem, 4cqi, 1.5rem);
    }
}
  

Typography scales with container, not viewport — ideal for design systems.

Style Queries (Emerging)

Query computed styles of container (limited browser support — check caniuse):

  @container style(--theme: dark) {
    .card { background: #1a1a2e; }
}
  

Container Query vs Media Query

Scenario Use
Page-level breakpoints Media query
Reusable component adapts to slot width Container query
Sidebar vs main column same component Container query
Mobile navigation toggle Media query

Practical Patterns

Responsive Card Grid Item

  .product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 1rem;
}

.product-cell {
    container-type: inline-size;
}

@container (min-width: 280px) {
    .product {
        flex-direction: row;
    }
    .product__details { padding-left: 1rem; }
}
  

Hide Labels in Narrow Containers

  @container (max-width: 200px) {
    .stat-label { display: none; }
    .stat-value { font-size: 1.25rem; }
}
  

Container-Aware Navigation

  .nav-container {
    container-type: inline-size;
}

@container (max-width: 400px) {
    .nav { flex-direction: column; }
    .nav__links { display: none; }
    .nav__menu-btn { display: block; }
}
  

Fallback for Unsupported Browsers

  .card { display: block; }

@supports (container-type: inline-size) {
    .card-wrapper { container-type: inline-size; }

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

Container queries supported in all modern browsers (Chrome 105+, Safari 16+, Firefox 110+).

Performance Considerations

  • Container queries create size containment — layout calculations scoped to container
  • Avoid deep nesting of query containers
  • Don’t set container-type: size unless you need both dimensions — requires explicit height

Best Practices

  1. Set container on wrapper, not the component itself
  2. Use inline-size unless height-based queries needed
  3. Name containers in complex nested layouts
  4. Combine with media queries — page structure vs component behavior
  5. Test component in multiple contexts — sidebar, modal, full width

Troubleshooting

Container query not applying

  • Verify ancestor has container-type set
  • Component must be descendant of container, not the container itself

Query never matches

  • Check container has defined width (not width: auto collapsing to zero)
  • Use DevTools → Elements → container badge (Chrome)

Unexpected layout with size containment

  • container-type: size requires explicit height on container

Container queries complete the responsive design story — build components that adapt to their environment, not just the viewport.