Pendant vingt ans, l’adaptation des interfaces a reposé sur une seule référence : la largeur de la fenêtre du navigateur. Les media queries interrogent le viewport, jamais l’espace réellement disponible autour d’un composant. Les container queries lèvent cette limite en laissant un élément répondre à la taille de son conteneur. Un même bloc peut alors s’afficher en version compacte dans une barre latérale et en version étendue au centre de la page, sans dépendre de la résolution de l’écran.
Le principe : interroger le conteneur, pas la fenêtre
Le mécanisme tient en deux temps. Un élément parent est déclaré comme conteneur de requête ; ses descendants peuvent ensuite conditionner leur mise en forme à la taille de ce conteneur. La déclaration se fait avec la propriété container-type, complétée au besoin d’un nom via container-name.
.card-container {
container-type: inline-size;
container-name: card;
}
/* The card reacts to its container width, not the viewport */
@container card (min-width: 30rem) {
.card {
display: grid;
grid-template-columns: 12rem 1fr;
gap: 1.5rem;
}
}La valeur inline-size demande au navigateur de surveiller la dimension en ligne, soit la largeur en écriture horizontale, tout en laissant la hauteur libre. C’est le réglage le plus courant, car il évite les effets de bord d’un confinement sur les deux axes. Comme le positionnement d’ancrage, les container queries retirent un pan de code JavaScript autrefois nécessaire pour mesurer les éléments.
Les unités de conteneur
Aux media queries répondaient les unités relatives au viewport comme vw et vh. Les container queries introduisent leurs propres unités, calculées sur la taille du conteneur de requête le plus proche. Elles permettent de dimensionner typographie et espacements proportionnellement au composant.
| Unité | Référence | Équivalent viewport |
|---|---|---|
cqw | 1 % de la largeur du conteneur | vw |
cqh | 1 % de la hauteur du conteneur | vh |
cqi | 1 % de la taille en ligne | vi |
cqb | 1 % de la taille de bloc | vb |
cqmin | la plus petite des deux | vmin |
cqmax | la plus grande des deux | vmax |
.card h3 {
/* Fluid heading, indexed on the container width */
font-size: clamp(1rem, 4cqi, 1.75rem);
}Un composant, deux contextes
L’intérêt se mesure sur un composant réutilisé à plusieurs endroits. La même carte produit, placée dans une grille à trois colonnes ou dans un bandeau pleine largeur, adopte deux mises en forme sans qu’une seule media query globale ne soit écrite. Le balisage reste identique ; seule la largeur du conteneur décide.
<div class="card-container">
<article class="card">
<img src="/product.jpg" alt="" />
<div class="body">
<h3>Product name</h3>
<p>Short description.</p>
</div>
</article>
</div>Media queries et container queries : complémentaires
Les container queries ne remplacent pas les media queries, elles les complètent. La structure générale de la page, ses gouttières de gabarit et ses grands points de bascule restent pilotés par le viewport, car ils dépendent réellement de la taille de l’écran et de l’orientation de l’appareil. Les container queries prennent le relais à l’intérieur, au niveau des composants réutilisables, là où la largeur disponible varie d’un emplacement à l’autre. Les deux mécanismes cohabitent dans la même feuille de style sans se gêner : au concepteur de tracer la frontière, en réservant le viewport à la mise en page d’ensemble et le conteneur au comportement des briques d’interface.
Nommer et imbriquer les conteneurs
La propriété raccourcie container réunit le type et le nom en une seule déclaration. Nommer ses conteneurs devient vite indispensable dès qu’ils s’imbriquent : une requête sans nom cible le conteneur ancêtre le plus proche, qui n’est pas toujours celui attendu. En attribuant un nom explicite, la requête vise sans ambiguïté le bon niveau, même à travers plusieurs conteneurs emboîtés. Cette discipline de nommage rejoint celle d’un système de composants : chaque zone majeure de la page, barre latérale, contenu principal ou pied de carte, gagne à porter un nom stable, réutilisé par les composants qu’elle héberge.
/* Shorthand: type and name in one declaration */
.sidebar { container: rail / inline-size; }
.main { container: content / inline-size; }
/* The query targets the nearest named container */
@container rail (max-width: 20rem) {
.widget { font-size: 0.875rem; }
}Déploiement progressif
La fonctionnalité est disponible dans les versions récentes des principaux navigateurs, mais un site à large audience conserve toujours une part de visiteurs sur d’anciennes versions. L’amélioration progressive répond à ce cas : la règle @supports n’active la mise en forme conditionnelle que là où container-type est reconnu, et laisse ailleurs une présentation de repli parfaitement lisible. Le composant reste fonctionnel partout, simplement enrichi là où le navigateur le permet. Cette approche évite le piège classique du tout ou rien, où une fonctionnalité récente casse l’affichage sur les configurations plus anciennes.
/* Progressive enhancement: only opt in when supported */
@supports (container-type: inline-size) {
.card-container { container-type: inline-size; }
}Typographie et contenu qui reflue
Au-delà de la disposition, les container queries affinent la typographie. Combinées aux unités cq* et à la fonction clamp(), elles produisent des tailles de texte qui suivent la largeur du composant sans paliers brutaux. Le confort de lecture est préservé quand un même bloc passe d’une colonne étroite à une pleine largeur. Une réserve toutefois : indexer une taille de police uniquement sur le conteneur peut nuire à l’accessibilité si l’échelle ignore les préférences de l’utilisateur. La bonne pratique consiste à borner les valeurs avec clamp() et à conserver une base en unités relatives, afin que le zoom et les réglages système restent respectés.
Ce que les container queries ne font pas
Un élément ne peut pas s’interroger lui-même : la requête porte toujours sur un conteneur ancêtre, jamais sur l’élément qui déclare container-type. Le confinement a aussi un coût de rendu, à réserver aux composants qui en tirent parti plutôt qu’à la racine du document. Enfin, les style queries étendent le principe aux propriétés personnalisées du conteneur, utiles en complément des design tokens.
/* Style query: react to a custom property on the container */
@container style(--density: compact) {
.card { padding: 0.5rem; }
}Un composant cesse d’être responsive à l’échelle de la page pour le devenir à l’échelle de son emplacement.
Point de vigilance : déclarer container-type: size confine les deux axes et exige une hauteur explicite, sous peine de faire disparaître le contenu. Dans la grande majorité des cas, inline-size est le bon choix.
Ce qu’il faut retenir
Les container queries déplacent la logique responsive du document vers le composant. Associées aux unités cq* et, bientôt partout, aux style queries, elles rendent les bibliothèques d’interface réellement portables d’un contexte à l’autre. Elles complètent une famille de fonctionnalités CSS modernes aux côtés des View Transitions, qui réduisent d’autant la dépendance au JavaScript.
J’ai longtemps dupliqué des composants pour gérer leurs variantes selon l’emplacement. Depuis que je m’appuie sur les container queries, je maintiens un seul composant et je le laisse s’adapter là où il est posé : mon CSS a maigri et mes revues de code aussi. C’est l’un des rares changements qui simplifie à la fois le code et l’architecture. — Simon Janvier
Pour aller plus loin
Documentation de référence : Container queries sur MDN.
