frontend / css
Container queries
Explication
Ce que vous allez apprendre
- Comprendre la limite fondamentale des media queries face à un composant réutilisable
- Déclarer un élément comme conteneur observable avec
container-type - Écrire des règles
@containerqui réagissent à la largeur du conteneur, pas du viewport - Utiliser les unités relatives au conteneur (
cqi,cqw) pour un texte fluide - Choisir entre
inline-sizeetsizeselon le besoin réel d'observation
Dans quel contexte ?
Le composant <carte-produit> doit s'afficher en ligne (image à gauche, texte à droite) quand il est dans la zone principale large de catalogue.html, mais en colonne compacte quand il est réutilisé dans la sidebar étroite "Produits similaires" de fiche-produit.html. Une media query est incapable de faire cette distinction, puisque le viewport reste identique dans les deux cas. En déclarant la sidebar et la zone principale comme container-type: inline-size, la même carte s'adapte automatiquement à la largeur réelle de l'endroit où elle est posée.
Étape 1 : l'angle mort des media queries
Les media queries vues à la leçon précédente ont une limite importante : elles ne connaissent QUE la taille du viewport, jamais la taille réelle de l'espace disponible pour un composant particulier.
Étape 2 : un exemple concret du problème
Une même carte produit peut se retrouver écrasée dans une sidebar étroite de 280px, ou confortablement large dans une zone principale de 900px — sur un écran qui, lui, n'a pas changé de taille. Une media query est incapable de faire cette distinction.
Étape 3 : la solution, réagir au conteneur
Les container queries résolvent ce problème en permettant à un élément de réagir à la taille de SON PROPRE conteneur parent, plutôt qu'à celle de la fenêtre entière.
Étape 4 : ce que ça change pour la conception
Un composant peut désormais s'adapter automatiquement où qu'il soit placé sur la page, sans qu'un développeur écrive une variante pour "quand c'est dans la sidebar" et une autre pour "quand c'est dans le contenu principal".
Étape 5 : deux étapes indissociables
La technique fonctionne en deux temps. D'abord, on déclare explicitement un élément comme "container" avec container-type — un conteneur ordinaire n'est pas automatiquement observable. Ensuite, on écrit des règles @container qui réagissent à la largeur de CE conteneur précis.
container-type | Observe | Contrainte |
|---|---|---|
inline-size | Largeur uniquement | Aucune, le cas le plus courant |
size | Largeur ET hauteur | Le conteneur doit avoir une taille explicite |
Prérequis
Cette leçon suppose une bonne maîtrise des media queries (leçon précédente) et de Flexbox/Grid, les container queries s'utilisant pour adapter la mise en page interne d'un composant.
Étape 6 : le piège de container-type: size
Il reste un piège à connaître : contrairement à inline-size (qui observe uniquement la largeur), container-type: size observe aussi la hauteur, mais impose en contrepartie que le conteneur ait une taille explicite, sinon son comportement devient imprévisible.
Piège fréquent
Utiliser container-type: size sur un conteneur dont la hauteur dépend justement de son contenu crée une dépendance circulaire que le navigateur ne peut pas résoudre proprement. Réservez size aux conteneurs à taille fixe, et préférez inline-size dans tous les autres cas.
Et ensuite ?
Une fois les container queries comprises, la prochaine étape consiste à centraliser les valeurs répétées du projet avec les variables CSS et les thèmes.
Commandes & code
Container queries
Adapter un composant à la taille de son CONTENEUR, pas à celle du viewport entier.
/* Le problème que résolvent les container queries :
une media query ne sait pas si un composant est dans une sidebar étroite
ou une zone principale large -- elle ne voit QUE la largeur de l'écran. */
.sidebar { width: 280px; }
.contenu-principal { width: 900px; }
/* la MÊME .carte-produit doit s'afficher différemment dans ces deux contextes,
alors que le viewport, lui, n'a pas changé *//* 1. Déclarer un élément comme container */
.sidebar,
.contenu-principal {
container-type: inline-size; /* observe uniquement la largeur (le cas le + courant) */
container-name: zone; /* nom optionnel, pratique si plusieurs containers imbriqués */
}
/* 2. Adapter les enfants selon LA TAILLE DU CONTAINER, pas du viewport */
.carte-produit {
display: flex;
flex-direction: column;
}
@container zone (min-width: 400px) {
.carte-produit {
flex-direction: row; /* passe en ligne dès que SON conteneur dépasse 400px */
gap: 16px;
}
}
@container zone (min-width: 700px) {
.carte-produit .description {
display: block; /* affiche la description seulement si vraiment la place */
}
}/* Unités relatives au container : cqw, cqh, cqi, cqb, cqmin, cqmax */
.titre-carte {
/* fluide par rapport au CONTAINER, pas au viewport */
font-size: clamp(1rem, 8cqi, 1.5rem);
/* cqi = inline-size du container (largeur, en écriture LTR/RTL horizontale) */
}/* container-type: size vs inline-size */
.widget-a {
container-type: inline-size; /* le plus courant : observe la largeur uniquement,
ne casse pas le flux de hauteur naturel */
}
.widget-b {
container-type: size; /* observe largeur ET hauteur, mais IMPOSE un containment
strict -> le conteneur doit avoir une taille explicite */
}
/* style queries (récent, support encore partiel) : interroge une custom property */
@container style(--theme: dark) {
.carte { background: #111; color: #eee; }
}Résumé
container-type: inline-sizetransforme un élément en point de référence pour ses enfants.@containerréagit à la taille du conteneur réel, indépendamment du viewport global.- Les unités
cqw/cqi/cqhpermettent un dimensionnement fluide relatif au container. - Un composant devient vraiment réutilisable : son style ne dépend plus d'où il est placé sur la page.
Exercices pratiques
Mission : une carte produit qui refuse de s'adapter à la sidebar
Objectif : Diagnostiquer pourquoi une media query ne suffit pas pour un composant réutilisable, puis mettre en place une container query fonctionnelle.
Contexte
Sur catalogue.css, .carte-produit utilise @media (min-width: 400px) { .carte-produit { flex-direction: row; } } pour passer en ligne quand il y a de la place. Le composant s'affiche bien en ligne dans la zone principale (900px de large), mais reste bêtement en ligne dans la sidebar "Produits similaires" de 280px de large, où il devrait rester en colonne — le viewport, lui, dépasse toujours 400px de large sur cet écran desktop.