Utilisez des requêtes de style (@container style()) pour déclencher des variations contextuelles sans coder en dur ce qui produit ou réagit à chaque contexte. Cela réduit le couplage du système de conception, et améliore l'extensibilité et l'encapsulation des composants.
Par exemple, une règle section.featured { --surface: featured } peut marquer un contexte, et une page de destination peut également l'utiliser par défaut via main { --surface: featured }. Les composants choisissent ensuite de réagir à --surface: featured : une fiche affiche un badge promotionnel, un bouton utilise par défaut sa variante pleine, etc.
Les requêtes de style permettent aux deux côtés de rester dissociés : les surfaces présentées ne nomment jamais les éléments qui s'y adaptent, et les composants n'inspectent jamais ce qui a produit le contexte. Chaque côté peut être étendu indépendamment (nouveaux composants, nouvelles surfaces d'affichage) sans toucher à l'autre. Les sélecteurs descendants (par exemple, .featured .button) imposent l'inverse : le sélecteur doit encoder les deux côtés de la relation et doit changer chaque fois que l'un des côtés change.
Quand utiliser ce guide ?
Ce guide traite des changements de comportement : un composant qui décide quoi afficher, comment s'organiser ou quelle variante présenter en réponse à son contexte (masquer ou afficher un badge, changer la direction de la mise en page ou changer de variante de bouton).
Si vous avez besoin de modifications au niveau des jetons (modes de densité, thèmes ou autres jetons d'ordre supérieur qui modifient uniformément des valeurs telles que la marge intérieure et la couleur dans de nombreux composants), consultez Réactivité des jetons de conception.
Choisir le bon outil
Utilisez une requête de style lorsque les deux côtés d'une relation contextuelle peuvent changer indépendamment : de nouveaux éléments peuvent commencer à produire le contexte, ou de nouveaux composants peuvent commencer à y réagir. L'indirection est rentable en termes d'extensibilité et d'encapsulation, et les requêtes de style franchissent les limites du Shadow DOM, ce que les sélecteurs descendants ne peuvent pas faire. Lorsque cette flexibilité n'est pas nécessaire, privilégiez l'outil le plus simple :
- Sélecteurs descendants (
.toolbar .button) : relation fixe et ponctuelle qui n'est ni réutilisable, ni extensible. Le principe YAGNI s'applique : n'ajoutez pas d'indirection que vous n'utiliserez pas. - Requêtes de taille (
@container (min-width: …)) : modifications de la mise en page et de la densité en fonction de l'espace disponible, et non de l'état sémantique. - Requêtes de style (
@container style(…)) : état sémantique, c'est-à-dire ce qu'un composant doit afficher, organiser ou présenter dans un contexte donné.
Directives d'implémentation
- Définissez un flag de contexte sémantique à l'aide d'une propriété CSS personnalisée sur un conteneur.
- NE DÉFINISSEZ PAS
container-typepour les requêtes de style. Elles interrogent les propriétés personnalisées héritées de l'ancêtre le plus proche et ne nécessitent pas de contexte de confinement explicite. - OBLIGATOIRE : Utilisez
@container style(--property: value)pour appliquer des styles conditionnels aux éléments descendants. Les requêtes de style ne peuvent pas correspondre à l'élément sur lequel la propriété est définie, mais uniquement à ses descendants. - À FAIRE : privilégiez les requêtes de style aux sélecteurs descendants lorsque la relation doit rester extensible ou franchir les limites des composants/du DOM fantôme (voir Choisir le bon outil ci-dessus). En revanche, conservez les sélecteurs descendants pour les relations fixes et ponctuelles où l'indirection n'apporte rien.
Exemple d'implémentation
/* 1. Set the context on a layout container */
.featured {
--surface: featured; /* Semantic context flag for children */
}
/* 2. Component reacts to inherited flag */
.button {
/* Default: Outlined informational style */
background: transparent;
border: 1px solid currentColor;
}
.badge {
/* Default: Hidden — only revealed in featured surfaces */
display: none;
}
@container style(--surface: featured) {
.button {
/* Automatic switch to Filled promotional style */
background: var(--brand-accent);
color: white;
border: none;
}
.badge {
/* Reveal decorative elements only in featured context */
display: block;
}
}
Stratégies de remplacement
En attendant que les requêtes de style de conteneur soient largement disponibles, superposez-les en tant qu'amélioration progressive : fournissez une valeur par défaut basée sur un sélecteur qui fonctionne partout, et laissez la requête de style la remplacer lorsqu'elle est prise en charge. Utilisez :where() sur le sélecteur de contexte pour que la requête de style (même spécificité, plus tard dans l'ordre de la source) l'emporte automatiquement.
/* Default styles — work everywhere */
.button {
background: transparent;
border: 1px solid currentColor;
}
.badge {
display: none;
}
/* Selector-based contextual styles — broad browser support */
:where(.featured) .button {
background: var(--brand-accent);
color: white;
border: none;
}
:where(.featured) .badge {
display: block;
}
/* Progressive enhancement: style queries override when supported */
@container style(--surface: featured) {
.button {
background: var(--brand-accent);
color: white;
border: none;
}
.badge {
display: block;
}
}
Le sélecteur de remplacement associe le style contextuel à un nom de classe, ce qui lie le composant à son emplacement dans le DOM. Une fois que les requêtes de style seront largement acceptées, la règle :where() pourra être supprimée.