Utiliser des requêtes de conteneur

Récemment, Chris Coyier a publié un article de blog sur la question:

Maintenant que les requêtes de conteneur sont compatibles avec tous les moteurs de navigateur, pourquoi les développeurs ne les utilisent-ils plus ?

Le post de Christophe énumère un certain nombre de raisons possibles (par exemple, un manque de conscience ou de vieilles habitudes qui meurent dure), mais une raison particulière ressorte.

Certains développeurs souhaitent utiliser des requêtes de conteneur dès maintenant, mais pensent que cela n'est pas possible, car ils doivent encore être compatibles avec les navigateurs plus anciens.

Comme vous l'avez peut-être deviné dans le titre, nous pensons qu'il est possible pour la plupart des développeurs d'utiliser des requêtes de conteneur dès maintenant (en production), même si vous devez prendre en charge des navigateurs plus anciens. Cet article vous présente la méthode que nous recommandons pour cela.

Une approche pragmatique

Si vous souhaitez utiliser des requêtes de conteneur dans votre code maintenant, mais que l'expérience soit la même dans tous les navigateurs, vous pouvez implémenter une solution de remplacement basée sur JavaScript pour les navigateurs qui n'acceptent pas les requêtes de conteneur.

La question est alors la suivante: quelle devrait être l'exhaustivité de la création de remplacement ?

Comme pour toute création de remplacement, la difficulté consiste à trouver un bon équilibre entre utilité et performances. Pour les fonctionnalités CSS, il est souvent impossible de prendre en charge l'API complète (voir pourquoi ne pas utiliser un polyfill). Cependant, vous pouvez aller assez loin en identifiant l'ensemble de fonctionnalités de base que la plupart des développeurs souhaitent utiliser, puis optimiser la création de remplacement uniquement pour ces fonctionnalités.

Mais qu'est-ce que l'ensemble de fonctionnalités de base ? que la plupart des développeurs veulent pour les requêtes avec conteneur ? Pour répondre à cette question, réfléchissez à la manière dont la plupart des développeurs conçoivent des sites responsifs avec des requêtes média.

Presque tous les systèmes de conception et les bibliothèques de composants modernes ont standardisé les principes de priorité à la mobilité, implémentés à l'aide d'un ensemble de points d'arrêt prédéfinis (tels que SM, MD, LG, XL). Par défaut, les composants sont optimisés pour s'afficher correctement sur les petits écrans, et les styles sont superposés de manière conditionnelle pour prendre en charge un ensemble fixe de largeurs d'écran plus grandes. (Consultez la documentation Bootstrap et Tailwind pour obtenir des exemples.)

Cette approche est tout aussi pertinente pour les systèmes de conception basés sur des conteneurs que pour les systèmes de conception basés sur des fenêtres d'affichage, car, dans la plupart des cas, ce qui intéresse les concepteurs n'est pas la taille de l'écran ou de la fenêtre d'affichage, mais de l'espace disponible pour le composant dans le contexte dans lequel il est placé. En d'autres termes, au lieu d'être liés à l'ensemble de la fenêtre d'affichage (et applicables à toute la page), ils s'appliquent à des zones de contenu spécifiques, telles que les barres latérales, les boîtes de dialogue modales ou le corps des articles.

Si vous êtes en mesure de respecter les contraintes d'une approche mobile first et basée sur des points d'arrêt (ce que font actuellement la plupart des développeurs), il est beaucoup plus facile d'implémenter une solution de remplacement basée sur des conteneurs que d'implémenter une compatibilité totale avec chaque fonctionnalité de requête de conteneur.

La section suivante explique en détail comment tout cela fonctionne et propose également un guide par étapes sur la façon de le mettre en œuvre sur un site existant.

Fonctionnement

Étape 1: Mettez à jour vos styles de composants pour utiliser des règles @container au lieu de règles @media

Au cours de cette première étape, identifiez les composants de votre site qui, selon vous, pourraient bénéficier d'un dimensionnement basé sur le conteneur plutôt que sur la fenêtre d'affichage.

Nous vous recommandons de commencer avec un ou deux composants seulement pour observer le fonctionnement de cette stratégie. Toutefois, si vous souhaitez convertir 100% de vos composants au style basé sur des conteneurs, ce n'est pas un problème. L'avantage de cette stratégie est que vous pouvez l'adopter progressivement si nécessaire.

Une fois que vous avez identifié les composants à mettre à jour, vous devez modifier chaque règle @media de ces composants à une règle @container.

Voici un exemple de ce à quoi cela peut ressembler sur un composant .photo-gallery qui, par défaut, est une colonne unique, puis qui utilise les règles @media pour modifier sa mise en page en deux et trois colonnes dans les points d'arrêt MD et XL (respectivement):

.photo-gallery {
  display: grid;
  grid-template-columns: 1fr;
}

/* Styles for the `MD` breakpoint */
@media (min-width: 800px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr;
  }
}

/* Styles for the `XL` breakpoint */
@media (min-width: 1200px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

Pour mettre à jour le composant .photo-gallery afin qu'il utilise des règles @container, commencez par remplacer la chaîne @media par la chaîne @container dans le CSS. La grammaire de ces deux règles est suffisamment similaire pour que, dans de nombreux cas, vous n'ayez rien à modifier.

Selon la conception de votre site, vous devrez peut-être également mettre à jour la condition de taille, en particulier si les règles @media de votre site font certaines hypothèses concernant l'espace disponible pour des composants spécifiques dans différentes tailles de fenêtre d'affichage.

Par exemple, si les styles du CSS .photo-gallery au niveau des points d'arrêt MD et XL de l'exemple précédent supposent qu'une barre latérale de 200 pixels de largeur sera affichée à ces points d'arrêt, les conditions de taille des règles @container devraient être inférieures d'environ 200 pixels, en supposant que le "conteneur" du composant .photo-gallery n'inclut pas la barre latérale.

Pour convertir le CSS .photo-gallery des règles @media en règles @container, vous devez apporter les modifications suivantes:

/* Before, using the original breakpoint sizes: */
@media (min-width: 800px) { /* ... */ }
@media (min-width: 1200px) { /* ... */ }

/* After, with the breakpoint sizes reduced by 200px: */
@container (min-width: 600px) { /* ... */ }
@container (min-width: 1000px) { /* ... */ }

Notez qu'il n'est pas nécessaire de modifier les styles dans le bloc de déclaration. En effet, ceux-ci reflètent l'apparence du composant plutôt que le moment où des styles spécifiques doivent s'appliquer.

Une fois les styles de composants des règles @media remplacés par des règles @container, l'étape suivante consiste à configurer les éléments de votre conteneur.

Étape 2: Ajoutez des éléments conteneurs à votre code HTML

L'étape précédente a défini des styles de composants basés sur la taille d'un élément de conteneur. L'étape suivante consiste à définir sur votre page les éléments de conteneur dont la taille sera relative aux règles @container.

Vous pouvez déclarer n'importe quel élément comme élément de conteneur dans CSS en définissant sa propriété container-type sur size ou inline-size. Si vos règles de conteneur sont basées sur la largeur, vous devez généralement utiliser inline-size.

Prenons l'exemple d'un site présentant la structure HTML de base suivante:

<body>
  <div class="sidebar">...</div>
  <div class="content">...</div>
</body>

Pour que les éléments .sidebar et .content de ce site soient des conteneurs, ajoutez la règle suivante à votre CSS:

.content, .sidebar {
  container-type: inline-size;
}

Pour les navigateurs qui acceptent les requêtes de conteneur, ce CSS suffit pour définir les styles de composants définis à l'étape précédente par rapport à la zone de contenu principal ou à la barre latérale, en fonction de l'élément dans lequel ils se trouvent.

Toutefois, pour les navigateurs qui n'acceptent pas les requêtes de conteneur, vous devrez effectuer des opérations supplémentaires.

Vous devez ajouter du code qui détecte quand la taille des éléments du conteneur change, puis met à jour le DOM en fonction de ces changements, de sorte que votre CSS puisse s'intégrer.

Heureusement, le code nécessaire pour effectuer cette opération est minime. Il peut être complètement extrait dans un composant partagé que vous pouvez utiliser sur n'importe quel site et dans n'importe quelle zone de contenu.

Le code suivant définit un élément <responsive-container> réutilisable qui écoute automatiquement les changements de taille et ajoute des classes de points d'arrêt sur lesquelles votre CSS peut appliquer un style:

// A mapping of default breakpoint class names and min-width sizes.
// Redefine these (or add more) as needed based on your site's design.
const defaultBreakpoints = {SM: 400, MD: 600 LG: 800, XL: 1000};

// A resize observer that monitors size changes to all <responsive-container>
// elements and calls their `updateBreakpoints()` method with the updated size.
const ro = new ResizeObserver((entries) => {
  entries.forEach((e) => e.target.updateBreakpoints(e.contentRect));
});

class ResponsiveContainer extends HTMLElement {
  connectedCallback() {
    const bps = this.getAttribute('breakpoints');
    this.breakpoints = bps ? JSON.parse(bps) : defaultBreakpoints;
    this.name = this.getAttribute('name') || '';
    ro.observe(this);
  }
  disconnectedCallback() {
    ro.unobserve(this);
  }
  updateBreakpoints(contentRect) {
    for (const bp of Object.keys(this.breakpoints)) {
      const minWidth = this.breakpoints[bp];
      const className = this.name ? `${this.name}-${bp}` : bp;
      this.classList.toggle(className, contentRect.width >= minWidth);
    }
  }
}

self.customElements.define('responsive-container', ResponsiveContainer);
<ph type="x-smartling-placeholder">

Ce code crée un ResizeObserver qui écoute automatiquement les modifications de taille de tous les éléments <responsive-container> dans le DOM. Si le changement de taille correspond à l'une des tailles de point d'arrêt définies, une classe portant ce nom de point d'arrêt est ajoutée à l'élément (et supprimée si la condition ne correspond plus).

Par exemple, si la valeur width de l'élément <responsive-container> est comprise entre 600 et 800 pixels (selon les valeurs de point d'arrêt par défaut définies dans le code), les classes SM et MD seront ajoutées, comme suit:

<responsive-container class="SM MD">...</responsive-container>

Ces classes vous permettent de définir des styles de remplacement pour les navigateurs qui n'acceptent pas les requêtes de conteneur (voir l'étape 3: Ajouter des styles de remplacement à votre CSS).

Pour mettre à jour le code HTML précédent afin d'utiliser cet élément de conteneur, remplacez les éléments <div> de la barre latérale et du contenu principal par des éléments <responsive-container>:

<body>
  <responsive-container class="sidebar">...</responsive-container>
  <responsive-container class="content">...</responsive-container>
</body>

Dans la plupart des cas, vous pouvez simplement utiliser l'élément <responsive-container> sans aucune personnalisation, mais si vous avez besoin de le personnaliser, les options suivantes sont disponibles:

  • Tailles de point d'arrêt personnalisées:ce code utilise un ensemble de noms de classe de point d'arrêt et de tailles de largeur minimale par défaut, mais vous devez modifier ces valeurs par défaut afin qu'elles soient celles que vous souhaitez. Vous pouvez également remplacer ces valeurs élément par élément à l'aide de l'attribut breakpoints.
  • Conteneurs nommés:ce code accepte également les conteneurs nommés en transmettant un attribut name. Cela peut être important si vous devez imbriquer des éléments de conteneur. Pour en savoir plus, consultez la section Limites.

Voici un exemple qui définit ces deux options de configuration:

<responsive-container
  name='sidebar'
  breakpoints='{"bp4":400,"bp5":500,"bp6":600,"bp7":700,"bp8":800,"bp9":900,"bp10":1000}'>
</responsive-container>

Enfin, lorsque vous regroupez ce code, veillez à utiliser la détection de fonctionnalités et l'import() dynamique pour ne le charger que si le navigateur n'accepte pas les requêtes de conteneur.

if (!CSS.supports('container-type: inline-size')) {
  import('./path/to/responsive-container.js');
}

Étape 3: Ajoutez des styles de remplacement à votre CSS

La dernière étape de cette stratégie consiste à ajouter des styles de remplacement pour les navigateurs qui ne reconnaissent pas les styles définis dans les règles @container. Pour ce faire, dupliquez ces règles à l'aide des classes de point d'arrêt définies sur les éléments <responsive-container>.

En reprenant l'exemple .photo-gallery précédent, les styles de remplacement pour les deux règles @container peuvent se présenter comme suit:

/* Container query styles for the `MD` breakpoint. */
@container (min-width: 600px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr;
  }
}

/* Fallback styles for the `MD` breakpoint. */
@supports not (container-type: inline-size) {
  :where(responsive-container.MD) .photo-gallery {
    grid-template-columns: 1fr 1fr;
  }
}

/* Container query styles for the `XL` breakpoint. */
@container (min-width: 1000px) {
  .photo-gallery {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

/* Fallback styles for the `XL` breakpoint. */
@supports not (container-type: inline-size) {
  :where(responsive-container.XL) .photo-gallery {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

Dans ce code, pour chaque règle @container, il existe une règle équivalente qui correspond de manière conditionnelle à l'élément <responsive-container> si la classe de point d'arrêt correspondante est présente.

La partie du sélecteur correspondant à l'élément <responsive-container> est encapsulée dans un sélecteur de pseudo-classe fonctionnel :where(), afin que la spécificité du sélecteur de remplacement corresponde à celle du sélecteur d'origine dans la règle @container.

Chaque règle de remplacement est également encapsulée dans une déclaration @supports. Bien que ce ne soit pas strictement nécessaire au fonctionnement de la création de remplacement, cela signifie que le navigateur ignore complètement ces règles s'il accepte les requêtes de conteneur, ce qui peut généralement améliorer les performances de mise en correspondance des styles. Les outils de compilation ou les CDN peuvent également supprimer ces déclarations s'ils savent que le navigateur accepte les requêtes de conteneur et qu'il n'a pas besoin de ces styles de remplacement.

Le principal inconvénient de cette stratégie de remplacement est qu'elle vous oblige à répéter la déclaration de style deux fois, ce qui est à la fois fastidieux et sujet aux erreurs. Toutefois, si vous utilisez un préprocesseur CSS, vous pouvez l'extraire dans un mixin qui génère automatiquement la règle @container et le code de remplacement. Voici un exemple avec Sass:

@use 'sass:map';

$breakpoints: (
  'SM': 400px,
  'MD': 600px,
  'LG': 800px,
  'XL': 1000px,
);

@mixin breakpoint($breakpoint) {
  @container (min-width: #{map.get($breakpoints, $breakpoint)}) {
    @content();
  }
  @supports not (container-type: inline-size) {
    :where(responsive-container.#{$breakpoint}) & {
      @content();
    }
  }
}

Ensuite, une fois que vous disposez de ce mixin, vous pouvez mettre à jour les styles de composant .photo-gallery d'origine pour qu'ils se présentent comme suit, ce qui élimine complètement la duplication:

.photo-gallery {
  display: grid;
  grid-template-columns: 1fr;

  @include breakpoint('MD') {
    grid-template-columns: 1fr 1fr;
  }

  @include breakpoint('XL') {
    grid-template-columns: 1fr 1fr 1fr;
  }
}

Et c'est tout ce que vous avez à faire !

Récapitulatif

Pour récapituler, voici comment mettre à jour votre code pour utiliser des requêtes de conteneur avec une création de remplacement pour plusieurs navigateurs.

  1. Identifiez les composants auxquels vous souhaitez appliquer un style par rapport à leur conteneur, puis mettez à jour les règles @media dans leur CSS pour qu'elles utilisent les règles @container. Si ce n'est pas déjà fait, normalisez un ensemble de noms de points d'arrêt correspondant aux conditions de taille de vos règles de conteneur.
  2. Ajoutez le code JavaScript qui sous-tend l'élément <responsive-container> personnalisé, puis ajoutez l'élément <responsive-container> à toutes les zones de contenu de votre page auxquelles vous souhaitez que vos composants soient liés.
  3. Pour prendre en charge les navigateurs plus anciens, ajoutez à votre CSS des styles de remplacement qui correspondent aux classes de points d'arrêt qui sont automatiquement ajoutées aux éléments <responsive-container> de votre code HTML. Il est préférable d'utiliser un préprocesseur CSS pour éviter d'avoir à écrire les mêmes styles deux fois.

L'avantage de cette stratégie est qu'elle entraîne des coûts de configuration uniques. Une fois la configuration terminée, aucun effort supplémentaire n'est nécessaire pour ajouter de nouveaux composants et définir des styles relatifs à ces derniers.

Démonstration

Le meilleur moyen de comprendre l'interaction entre toutes ces étapes est probablement de regarder une démonstration en action.

<ph type="x-smartling-placeholder">
</ph> <ph type="x-smartling-placeholder"></ph> <ph type="x-smartling-placeholder">.
Vidéo d'un utilisateur interagissant avec le site de démonstration des requêtes de conteneur. L'utilisateur redimensionne les zones de contenu pour montrer comment les styles des composants sont mis à jour en fonction de la taille de la zone de contenu dans laquelle ils se trouvent.

Cette démonstration est une version mise à jour d'un site créé en 2019 (avant l'existence des requêtes de conteneur). Elle montre pourquoi ces requêtes sont essentielles à la création de bibliothèques de composants vraiment responsives.

Étant donné que des styles avaient déjà été définis pour un ensemble de "composants responsifs", ce site était un candidat idéal pour tester la stratégie présentée ici sur un site complexe. Il s'avère que la mise à jour a été assez simple et qu'elle n'a nécessité pratiquement aucune modification des styles d'origine du site.

Vous pouvez consulter le code source complet de la démonstration sur GitHub et consulter spécifiquement le CSS du composant "demo" pour savoir comment les styles de remplacement sont définis. Si vous souhaitez ne tester que le comportement de remplacement, une version de démonstration de remplacement uniquement qui inclut uniquement cette variante est disponible, même dans les navigateurs qui acceptent les requêtes de conteneur.

Limites et améliorations potentielles

Comme indiqué au début de cet article, la stratégie décrite ici fonctionne bien pour la majorité des cas d'utilisation qui intéressent réellement les développeurs lorsqu'ils utilisent des requêtes de conteneur.

Cela dit, il existe des cas d'utilisation plus avancés que cette stratégie ne cherche pas intentionnellement à prendre en charge. Voici quelques exemples:

Unités de requête du conteneur

La spécification des requêtes de conteneur définit le nombre de nouvelles unités qui sont toutes liées à la taille du conteneur. Bien que potentiellement utiles dans certains cas, la majorité des conceptions réactives peuvent probablement être réalisées par des moyens existants, tels que les pourcentages ou l’utilisation de mises en page en grille ou en flex.

Toutefois, si vous avez besoin d'utiliser des unités de requête de conteneur, vous pouvez facilement les rendre compatibles à l'aide de propriétés personnalisées. Plus précisément, en définissant une propriété personnalisée pour chaque unité utilisée dans l'élément conteneur, comme ceci:

responsive-container {
  --cqw: 1cqw;
  --cqh: 1cqh;
}

Ensuite, chaque fois que vous devez accéder aux unités de requête du conteneur, utilisez ces propriétés plutôt que l'unité elle-même:

.photo-gallery {
  font-size: calc(10 * var(--cqw));
}

Ensuite, pour assurer la compatibilité avec les navigateurs plus anciens, définissez les valeurs de ces propriétés personnalisées sur l'élément conteneur dans le rappel ResizeObserver.

class ResponsiveContainer extends HTMLElement {
  // ...
  updateBreakpoints(contentRect) {
    this.style.setProperty('--cqw', `${contentRect.width / 100}px`);
    this.style.setProperty('--cqh', `${contentRect.height / 100}px`);

    // ...
  }
}

Cela vous permet de transmettre efficacement ces valeurs de JavaScript à CSS. Vous avez alors toute la puissance du CSS (par exemple, calc(), min(), max(), clamp()) pour les manipuler si nécessaire.

Propriétés logiques et mode d'écriture

Vous avez peut-être remarqué l'utilisation de inline-size au lieu de width dans les déclarations @container de certains de ces exemples CSS. Vous avez peut-être également remarqué les nouvelles unités cqi et cqb (pour les tailles intégrées et de bloc, respectivement). Ces nouvelles fonctionnalités reflètent la transition du CSS vers des propriétés et valeurs logiques plutôt que des propriétés physiques ou directionnelles.

Malheureusement, les API telles que Resize Observer signalent toujours les valeurs dans width et height. Par conséquent, si vos conceptions ont besoin de la flexibilité des propriétés logiques, vous devez le déterminer vous-même.

Bien qu'il soit possible d'obtenir le mode d'écriture à l'aide d'un élément comme getComputedStyle() en transmettant l'élément de conteneur, cela a un coût et il n'existe pas vraiment de moyen efficace de détecter si le mode d'écriture change.

C'est pourquoi la meilleure approche consiste à ce que l'élément <responsive-container> lui-même accepte une propriété de mode d'écriture que le propriétaire du site peut définir (et mettre à jour) si nécessaire. Pour ce faire, suivez la même approche que celle présentée dans la section précédente, en remplaçant width et height selon vos besoins.

Conteneurs imbriqués

La propriété container-name vous permet d'attribuer un nom à un conteneur, que vous pouvez ensuite référencer dans une règle @container. Les conteneurs nommés sont utiles si certains de vos conteneurs sont imbriqués dans des conteneurs et que vous avez besoin que certaines règles correspondent uniquement à certains conteneurs (pas seulement le conteneur ancêtre le plus proche).

La stratégie de remplacement décrite ici utilise le combinateur descendant pour appliquer un style aux éléments correspondant à certaines classes de points d'arrêt. Cela peut s'avérer problématique dans le cas de conteneurs imbriqués, car un nombre illimité de classes de point d'arrêt provenant de plusieurs ancêtres d'éléments de conteneur peut correspondre à un composant donné à la fois.

Par exemple, ici, deux éléments <responsive-container> encapsulent le composant .photo-gallery, mais comme le conteneur externe est plus grand que le conteneur interne, des classes de points d'arrêt différentes ont été ajoutées.

<responsive-container class="SM MD LG">
  ...
  <responsive-container class="SM">
    ...
    <div class="photo-gallery">...</div class="photo-gallery">
  </responsive-container>
</responsive-container>

Dans cet exemple, les classes MD et LG du conteneur externe affectent les règles de style correspondant au composant .photo-gallery, qui ne correspond pas au comportement des requêtes de conteneur (car elles ne sont mises en correspondance qu'avec le conteneur d'ancêtre le plus proche).

Pour résoudre ce problème, deux options s'offrent à vous:

  1. Veillez à toujours nommer les conteneurs que vous imbriquez, puis assurez-vous que vos classes de point d'arrêt sont précédées du nom de ce conteneur pour éviter les conflits.
  2. Utilisez le combinateur enfant au lieu du combinateur descendant dans vos sélecteurs de remplacement (ce qui est un peu plus contraignant).

La section Conteneurs imbriqués du site de démonstration présente un exemple de ce fonctionnement à l'aide de conteneurs nommés, ainsi que le mixin Sass qu'il utilise dans le code afin de générer les styles de remplacement pour les règles @container nommées et non.

Qu'en est-il des navigateurs qui ne sont pas compatibles avec :where(), Custom Elements ou Resize Observer ?

Bien que ces API puissent sembler relativement récentes, elles sont toutes compatibles avec tous les navigateurs depuis plus de trois ans et font toutes partie de Baseline, largement disponible.

Par conséquent, sauf si vous disposez de données montrant qu'une part significative des visiteurs de votre site utilise des navigateurs non compatibles avec l'une de ces fonctionnalités, il n'y a aucune raison de ne pas les utiliser librement sans solution de secours.

Même dans ce cas d'utilisation spécifique, le pire qui pourrait se produire est que la création de remplacement ne fonctionnera pas pour un très petit pourcentage de vos utilisateurs. Cela signifie qu'ils verront la vue par défaut plutôt qu'une vue optimisée pour la taille du conteneur.

La fonctionnalité du site doit toujours fonctionner, et c'est ce qui compte vraiment.

Pourquoi ne pas simplement utiliser un polyfill de requête de conteneur ?

Les fonctionnalités CSS sont très difficiles à émuler et nécessitent généralement de réimplémenter l'intégralité de l'analyseur CSS et de la logique en cascade du navigateur en JavaScript. Par conséquent, les auteurs de polyfills CSS doivent faire de nombreux compromis qui s'accompagnent presque toujours de nombreuses limitations en termes de fonctionnalités ainsi que d'un impact important sur les performances.

C'est pourquoi nous déconseillons généralement d'utiliser les polyfills CSS en production, y compris le container-query-polyfill de Google Chrome Labs, dont la maintenance n'est plus assurée (et qui était principalement destinée à des fins de démonstration).

La stratégie de remplacement décrite ici présente moins de limites, nécessite beaucoup moins de code et offre des performances nettement supérieures à n'importe quel polyfill de requête de conteneur.

Avez-vous besoin d'implémenter une solution de secours pour les navigateurs plus anciens ?

Si l'une des limites mentionnées ici vous préoccupe, nous vous conseillons de vous demander si vous devez réellement implémenter une création de remplacement en premier lieu. Après tout, le moyen le plus simple d'éviter ces limites est d'utiliser la fonctionnalité sans aucune solution de secours. Honnêtement, dans de nombreux cas, cela peut être un choix tout à fait raisonnable.

D'après caniuse.com, les requêtes avec conteneur sont acceptées par 90% des internautes dans le monde. Or, pour de nombreuses personnes qui lisent cet article, ce nombre est sans doute un peu plus élevé pour leur base d'utilisateurs. Il est donc important de garder à l'esprit que la plupart de vos utilisateurs verront la version "container-query" de votre interface utilisateur. Et pour les 10% d'utilisateurs qui n'en auront pas, l'expérience ne sera pas frustrante. Si vous appliquez cette stratégie, dans le pire des cas, ces utilisateurs verront la valeur par défaut, ou "mobile", une mise en page pour certains composants, ce qui n'est pas la fin du monde.

Lorsque vous faites des compromis, il est recommandé d'optimiser vos campagnes pour la majorité de vos utilisateurs. Plutôt que d'adopter par défaut l'approche basée sur le plus petit dénominateur commun, qui offre à tous les utilisateurs une expérience cohérente, mais médiocre.

Par conséquent, avant de supposer que vous ne pouvez pas utiliser de requêtes de conteneur en raison d'une incompatibilité avec les navigateurs, prenez le temps de réfléchir à l'expérience qui vous serait proposée si vous choisissiez de les adopter. Le compromis peut en valoir la peine, même sans aucune solution de secours.

Et demain ?

Nous espérons que cet article vous a convaincu qu'il est possible d'utiliser des requêtes conteneur dès maintenant en production, et qu'il n'est pas nécessaire d'attendre des années que tous les navigateurs non compatibles disparaissent complètement.

Bien que la stratégie décrite ici nécessite quelques efforts supplémentaires, elle doit être suffisamment simple pour que la plupart des utilisateurs puissent l'adopter sur leur site. Cela dit, le processus d'adoption peut certainement être encore plus simple. Une idée serait de consolider de nombreuses parties disparates en un seul composant, optimisé pour un framework ou une pile spécifique, qui gère tout le travail à votre place. Si vous créez ce type de contenu, n'hésitez pas à nous contacter afin que nous puissions vous aider à en faire la promotion.

Enfin, au-delà des requêtes de conteneur, il existe de nombreuses fonctionnalités CSS et UI incroyables qui sont désormais interopérables sur tous les principaux moteurs de navigateur. Nous allons maintenant voir ensemble comment utiliser ces fonctionnalités pour en faire profiter nos utilisateurs.


Mise à jour (25 juillet 2024) : à l'origine, les consignes de l'étape 1 suggère que les requêtes média et les requêtes de conteneur peuvent utiliser les mêmes conditions de taille. C'est souvent vrai, mais pas toujours (comme certaines raisons ont été soulignées à juste titre). Les nouvelles consignes clarifient désormais ce point et proposent des exemples dans lesquels les conditions de taille peuvent avoir besoin de changer.

Mise à jour (2 juillet 2024) : à l'origine, tous les exemples de code CSS utilisaient Sass (pour des raisons de cohérence avec la recommandation finale). Suite aux commentaires des lecteurs, les premiers CSS ont été mis à jour vers du CSS ordinaire, et Sass n'est utilisé que dans les exemples de code nécessitant l'utilisation de mixins.