CSS Container Queries: Truly Responsive Components
For years, responsive design meant: "adapt the layout to the viewport."
A component card with @media (max-width: 768px) he knows how wide it is
the screen, but he doesn't know how much space he actually has available on his
context. Put that card in a narrow sidebar and it behaves as if it were
on mobile, even if the screen is a 27" desktop. Put it in the main content
and it behaves like a desktop even if that container is narrower than a smartphone.
Le CSS Container Queries solve this problem at the root: a component can react to the size of the own container, not of the viewport. With superior browser support88% in Baseline 2025 (Chrome 105+, Firefox 110+, Safari 16+), this technique is production ready.
What You Will Learn
- The fundamental difference between Media Queries and Container Queries
- How to define a containment context with
container-type - The syntax
@containerfor queries - Container size queries: inline-size, block-size
- Container style queries: queries based on custom properties
- Named containers for hierarchical queries
- How to integrate container queries into Angular, React and Vue
The Problem with Media Queries
Media queries query the characteristics of the viewport: the width of the screen, the orientation, the color scheme. This works when the layout and simple and a component always occupies a predictable width. But in the designs modern systems, the same component is reused in radically different contexts:
- A product card on the homepage (3 columns on desktop)
- The same card in the "related products" sidebar (1 narrow column)
- The same card in a fullscreen modal (2 columns)
- The same card on the search page (variable based on active filters)
With media queries, you have to know the context of each usage in advance and write case-specific CSS selectors. With container queries, the e autonomous: it adapts itself to its available space.
Define a Container
To use container queries, the first step is to declare which element is the
"container" that will be questioned. It is done with property container-type:
/* Crea un container che risponde alla larghezza (inline-size) */
.card-wrapper {
container-type: inline-size;
}
/* Crea un container che risponde sia a larghezza che altezza */
.card-wrapper {
container-type: size;
}
/* Dai un nome al container per query gerarchiche */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* Shorthand */
.card-wrapper {
container: card / inline-size;
}
Once an item has container-type, all his descendants
they can use @container to query its dimensions.
The Syntax @container
The syntax is identical to media queries, but instead of querying the viewport, query the nearest container with a containment context:
.card {
/* Layout default: verticale, compatto */
display: grid;
grid-template-areas:
"image"
"content";
gap: 12px;
}
.card__image {
aspect-ratio: 16 / 9;
object-fit: cover;
border-radius: 8px 8px 0 0;
}
/* Quando il container e largo almeno 400px: layout orizzontale */
@container (min-width: 400px) {
.card {
grid-template-areas: "image content";
grid-template-columns: 200px 1fr;
}
.card__image {
aspect-ratio: 1;
border-radius: 8px 0 0 8px;
}
}
/* Quando il container e largo almeno 600px: layout espanso */
@container (min-width: 600px) {
.card {
grid-template-columns: 280px 1fr;
gap: 24px;
padding: 24px;
}
.card__title {
font-size: 1.5rem;
}
}
/* Range syntax (CSS Level 4) - piu leggibile */
@container (200px <= width <= 400px) {
.card {
/* stile per range specifico */
}
}
Named Containers: Hierarchical Queries
When you have nested containers, you can name the containers to query a specific ancestor instead of closest:
<!-- HTML struttura -->
<main class="layout" style="container: layout / inline-size">
<aside class="sidebar" style="container: sidebar / inline-size">
<div class="widget">
<!-- Questo widget puo interrogare sia "sidebar" che "layout" -->
</div>
</aside>
</main>
/* Query sul container "sidebar" (il piu vicino) */
@container sidebar (min-width: 300px) {
.widget { display: flex; }
}
/* Query sul container "layout" (l'antenato nominato) */
@container layout (min-width: 1200px) {
.widget { max-width: 400px; }
}
Container Style Queries: The Hidden Feature
In addition to size queries, container queries also support style queries: queries based on the values of the container's CSS custom properties. This feature, supported in Chrome 111+ and Safari 17.4+, opens up possibilities completely new in terms of theming and component variants.
/* Definisci una custom property sul container */
.card-wrapper {
container-type: style;
/* La variante del componente viene comunicata via custom property */
--card-variant: featured;
}
/* Il componente si adatta alla variante del container */
@container style(--card-variant: featured) {
.card {
border: 2px solid var(--color-accent);
background: var(--color-accent-subtle);
}
.card__badge {
display: block; /* mostra il badge "In evidenza" */
}
}
@container style(--card-variant: compact) {
.card {
padding: 8px;
font-size: 0.875rem;
}
.card__image {
display: none; /* nasconde l'immagine in modalita compatta */
}
}
This pattern allows you to communicate semantic context from the container to the component without additional CSS or JavaScript classes, maintaining encapsulation.
Container measurement units: cqw, cqh, cqi, cqb
With container queries also come new units of measurement relating to the container:
cqw: 1% of the width of the containercqh: 1% of the container heightcqi: 1% of the container inline size (= cqw for LTR layout)cqb: 1% of the container block size (= cqh)cqmin: the smaller between cqi and cqbcqmax: the larger between cqi and cqb
/* Tipografia fluida relativa al container */
.card__title {
/* Scala da 16px a 24px in base alla larghezza del container */
font-size: clamp(1rem, 4cqi, 1.5rem);
}
/* Padding proporzionale al container */
.card {
padding: 5cqi;
}
/* Gap che si adatta */
.card__grid {
display: grid;
gap: clamp(8px, 2cqi, 24px);
}
Container Queries in Angular, React and Vue
Angular: Container-Aware Components
/* card.component.scss */
:host {
display: block;
container-type: inline-size;
container-name: card-host;
}
.card {
display: grid;
grid-template-areas: "image" "content";
gap: 12px;
}
@container card-host (min-width: 400px) {
.card {
grid-template-areas: "image content";
grid-template-columns: 180px 1fr;
}
}
// card.component.ts
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss'],
// :host come container - nessun JS necessario per il responsive
host: { class: 'card-container' }
})
export class CardComponent {
@Input() product!: Product;
}
React: CSS Modules with Container Queries
/* card.module.css */
.wrapper {
container-type: inline-size;
container-name: card;
}
.card {
display: grid;
gap: 12px;
}
@container card (min-width: 400px) {
.card {
grid-template-columns: 180px 1fr;
}
}
// Card.tsx
import styles from './card.module.css';
export function Card({ product }: { product: Product }) {
return (
<div className={styles.wrapper}>
<article className={styles.card}>
<img src={product.image} alt={product.name} />
<div>
<h3>{product.name}</h3>
<p>{product.description}</p>
</div>
</article>
</div>
);
}
Container Queries vs Media Queries: When to Use What
| Scenario | Optimal Choice | Reason |
|---|---|---|
| Global page layout | Media Queries | The layout depends on the viewport |
| Reusable components | Container Queries | The component must adapt to its context |
| Design system tokens | Both | Viewports for breakpoints, containers for variants |
| Dark/light mode | Media Queries | prefers-color-scheme and a media feature |
| Dynamic sidebar | Container Queries | Content fits in open/closed sidebar |
| Print styling | Media Queries | @media print is a media query |
Pattern Anti: Common Mistakes with Container Queries
Mistake #1: Container Querying Itself
An element with container-type he cannot question himself with
@container — it must be a descendant that is modified.
Never define a container and a rule @container on the same
selector.
Error #2: container-type: size without Height Defined
container-type: size requires the container to have a size
defined both in width and height. If you use size on a container
without explicit height, queries height e cqh
they will not work as expected. USA inline-size in the majority
of cases.
Next Steps
You now have truly responsive components thanks to container queries. The next article in the series explores the CSS Anchor Positioning API, which enables to implement tooltips, dropdowns and popovers without a single line of JavaScript: another technique that brings CSS closer to the declarative power that developers have been waiting for for years.
Conclusions
CSS Container Queries fundamentally change the way we build responsive components. Instead of a global breakpoint system that each component must know and respect, each component becomes autonomous and adapts to its own context. This leads to more maintainable code, truly composable design systems and fewer edge cases to manage manually.
With browser support above 88%, container queries are ready for deployment production today. The best way to get started and identify the components of the your design system that are used in multiple contexts — typically card, list item, media object — and progressively convert them to the new paradigm.







