Changer le thème

Mise en page responsive avec Tailwind : container queries et stratégie de breakpoints

Easton editorial illustration: guided setup bench

Chapeau

Vous fixez l’écran : ce composant carte.

Sur la page d’accueil, tout est parfait — image à gauche, texte à droite, espacements confortables. Copié dans la barre latérale, la mise en page s’effondre comme un papier froissé. L’image se compresse, le texte se casse n’importe comment.

Comment ce truc est-il censé savoir à quoi il doit ressembler ?

Le responsive classique ne regarde que le viewport — la fenêtre du navigateur. Le composant ignore la largeur du conteneur qui l’accueille. Comme quelqu’un habitué à une villa, jeté dans un studio de trente mètres carrés sans savoir où placer les meubles.

Les container queries Tailwind comblent ce trou : le composant perçoit la taille de son conteneur au lieu de ne regarder que la fenêtre.

Cet article couvre les deux pièges les plus fréquents du responsive Tailwind : choisir sa stratégie de breakpoints et utiliser les container queries. Beaucoup de code concret — cent lectures de doc ne valent pas un essai sur votre layout.

L’évolution du responsive : du viewport au conteneur

Media queries : les limites de l’ancienne méthode

Les media queries, on les utilise depuis des années ; elles semblent suffisantes — jusqu’au jour où la même carte doit aller dans trois contextes : flux d’accueil, encart latéral, liste dans une modale.

Le problème apparaît.

La media query mesure le viewport, pas ce qui compte pour le composant : la largeur du parent.

Exemple :

/* Media query classique */
@media (min-width: 768px) {
  .card {
    flex-direction: row;
  }
}

Signification : si la fenêtre dépasse 768px, la carte passe en horizontal.

Mais si le viewport fait 1200px et la barre latérale seulement 280px ? La carte reste horizontale et se tasse dans ce couloir étroit.

On a l’impression de chausser du 44 dans du 38.

Container queries : changer de question

La container query ne demande pas « quelle est la fenêtre ? » mais « quelle est mon boîte ? ».

/* Container query */
@container (min-width: 400px) {
  .card {
    flex-direction: row;
  }
}

Ici : quand le conteneur dépasse 400px, la carte passe en horizontal.

« Et alors ? » — la différence est énorme.

Même carte : zone de contenu à 600px → horizontal sans souci ; barre latérale à 280px → empilement vertical automatique. Pas de double composant, pas de props, pas de rafales de conditions.

Le composant devient enfin réutilisable.

Support navigateur

Vers 2023, les navigateurs majeurs ont généralisé les container queries. En 2024, le support des Container Size Queries dépasse 90 % — Chrome, Firefox, Safari, Edge.

Projets legacy : peut-être attendre encore un peu. Pour la plupart des sites actuels, c’est jouable.

Le système de breakpoints Tailwind CSS

Avant les container queries, clarifions les breakpoints Tailwind — c’est la base.

Les breakpoints par défaut

Cinq seuils par défaut :

PréfixeLargeur min.Scénario typique
sm:640pxGrand téléphone paysage
md:768pxTablette portrait
lg:1024pxTablette paysage / petit portable
xl:1280pxÉcran bureau
2xl:1536pxGrand écran

Pas besoin de tout mémoriser : l’essentiel est que Tailwind est mobile-firstmd:flex-row signifie « à partir de 768px de viewport, appliquer flex-row ».

Mobile-first : d’abord le petit écran

Par défaut, vous stylez le mobile, puis vous enrichissez avec les breakpoints.

<!-- Mobile-first -->
<div class="flex flex-col md:flex-row lg:gap-8">
  <!-- mobile : empilement vertical -->
  <!-- tablette (md) : horizontal -->
  <!-- bureau (lg) : espacement plus large -->
</div>

Styles simples d’abord, puis couches — utile pour les appareils modestes.

Le « desktop-first » impose des breakpoints inverses ; sauf contrainte projet, le mobile-first reste plus simple.

Quand personnaliser les breakpoints

La plupart du temps, les valeurs par défaut suffisent. Exceptions : design system avec des seuils custom.

Exemple : back-office avec 480px, 720px, 960px, 1200px — il faut toucher tailwind.config.js :

// tailwind.config.js
module.exports = {
  theme: {
    screens: {
      'xs': '480px',   // breakpoint plus petit
      'sm': '640px',
      'md': '720px',   // remplace la valeur par défaut
      'lg': '960px',
      'xl': '1200px',
    }
  }
}

Besoin d’un seuil sous sm pour très petits écrans :

screens: {
  'xs': '475px',   // nouveau
  'sm': '640px',
  // ... reste inchangé
}

Nommer les breakpoints

Piège personnel : nommer mobile, tablet, desktop. Pliants, écrans embarqués — les noms vieillissent mal.

Désormais : sm, md, lg — tailles, pas appareils. Les noms restent valables quand de nouveaux formats arrivent.

Container queries en pratique : faire « sentir » l’espace au composant

Cette section montre du code concret.

Étape 1 : déclarer le conteneur

Il faut dire au navigateur : cet élément est un conteneur de requête.

En Tailwind, une classe @container :

<!-- Parent -->
<div class="@container">
  <!-- Les enfants s'adaptent à la taille du conteneur -->
  <div class="flex flex-col @sm:flex-row">
    ...
  </div>
</div>

Ce div devient conteneur ; les enfants utilisent @sm, @md, etc.

Les breakpoints conteneur

Ils diffèrent des breakpoints viewport :

BreakpointLargeur min.
@xs320px
@sm384px
@md448px
@lg512px
@xl576px
@2xl672px
@3xl768px
@4xl896px
@5xl1024px

Plus petits que sm/md viewport — logique : le conteneur est imbriqué, il ne peut pas être plus large que la fenêtre.

Cas 1 : carte adaptive

Carte utilisable partout :

  • conteneur < 384px : vertical, image pleine largeur
  • conteneur >= 384px : horizontal, largeur d’image fixe
  • conteneur >= 512px : image plus grande, plus de lignes de texte
<!-- Parent : conteneur de requête -->
<div class="@container p-4">
  <article class="flex flex-col @sm:flex-row @lg:gap-6 bg-white rounded-lg shadow">
    <img
      src="https://example.com/image.jpg"
      alt="Illustration d'article"
      class="w-full @sm:w-32 @lg:w-48 h-48 @sm:h-32 @lg:h-36 object-cover rounded-t-lg @sm:rounded-l-lg @sm:rounded-tr-none"
    />

    <div class="p-4 @sm:py-2 @lg:py-4 flex-1">
      <h3 class="text-base @lg:text-lg font-semibold mb-2">
        Guide d'introduction aux container queries Tailwind
      </h3>
      <p class="text-sm text-gray-600 line-clamp-2 @lg:line-clamp-3">
        Comment utiliser les container queries Tailwind CSS pour un vrai responsive au niveau composant...
      </p>
      <div class="mt-3 flex items-center text-xs text-gray-400">
        <span>2026-03-27</span>
        <span class="mx-2">·</span>
        <span>5 min de lecture</span>
      </div>
    </div>
  </article>
</div>

Barre latérale 280px : layout vertical compact. Zone 600px : horizontal aéré. Même markup.

Cas 2 : barre de navigation réutilisable

La navigation illustre bien l’intérêt : même composant en en-tête large, barre latérale étroite, tiroir mobile.

<nav class="@container">
  <ul class="flex flex-col @lg:flex-row @lg:items-center gap-2 @lg:gap-6">
    <li>
      <a href="/" class="block py-2 px-3 rounded hover:bg-gray-100">
        Accueil
      </a>
    </li>
    <li>
      <a href="/posts" class="block py-2 px-3 rounded hover:bg-gray-100">
        Articles
      </a>
    </li>
    <li>
      <a href="/about" class="block py-2 px-3 rounded hover:bg-gray-100">
        À propos
      </a>
    </li>
  </ul>
</nav>

À partir de 512px de conteneur (@lg), les liens passent en ligne.

Un seul composant, plusieurs emplacements, sans variantes CSS par contexte.

Limites des container queries

1. Pas de requête sur la hauteur

Seule la largeur est supportée aujourd’hui.

/* N'a pas d'effet */
@container (min-height: 400px) {
  /* pas encore supporté */
}

2. Conteneur de taille requis

@container crée un conteneur de taille ; seuls ses descendants interrogent ce conteneur (ou un ancêtre conteneur plus proche, pas forcément le parent direct).

3. Peu d’imbrication

Trop de niveaux @container coûte en perf. Deux à trois niveaux max, puis refactor.

Choisir sa stratégie : media query vs container query

Critère simple : de quoi dépend le style ?

Arbre de décision

De quoi ce style dépend-il ?

├─ Viewport → media queries (md:, lg:, …)
│   ├─ Grille de page
│   ├─ Navigation globale, header, footer
│   ├─ Hero, bannières plein écran
│   └─ Éléments ancrés au viewport

└─ Conteneur → container queries (@sm:, @lg:, …)
    ├─ Composants réutilisables (cartes, lignes)
    ├─ Widgets de barre latérale
    ├─ Contenu de modale
    └─ Composants imbriqués

Scénarios media query

Mise en page de page : colonnes selon la fenêtre.

<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  <!-- cartes -->
</div>

Navigation globale : menu burger vs barre horizontale selon viewport.

<header class="flex items-center justify-between px-4 py-3">
  <div class="logo">Logo</div>

  <nav class="hidden md:flex gap-6">
    <a href="/">Accueil</a>
    <a href="/posts">Articles</a>
    <a href="/about">À propos</a>
  </nav>

  <button class="md:hidden">
    <span class="sr-only">Ouvrir le menu</span>
    <!-- icône hamburger -->
  </button>
</header>

Scénarios container query

Composants réutilisables : carte en flux d’accueil (~300–400px), recommandations (~250px), barre latérale (~280px).

Imbrication :

<div class="@container w-full md:w-80">
  <div class="@container">
    <div class="@sm:flex-row @lg:gap-4">
      ...
    </div>
  </div>
</div>

Combinaison

Page en media query, composants en container query :

<div class="grid grid-cols-1 md:grid-cols-3 gap-6">

  <main class="md:col-span-2">
    <div class="@container">
      <article class="flex flex-col @sm:flex-row">
        <!-- contenu carte -->
      </article>
    </div>
  </main>

  <aside class="@container">
    <div class="@sm:grid-cols-2">
      <!-- widgets -->
    </div>
  </aside>

</div>

Structure globale selon l’appareil ; détail interne selon l’espace réel — deux couches, deux rôles.

Performance et bonnes pratiques

Coût des container queries

Le navigateur calcule et observe les tailles de conteneur — coût faible sauf abus d’imbrication.

Erreur vue en prod : @container sur chaque item de liste, puis encore plusieurs niveaux — léger lag au scroll.

<!-- À éviter : @container à chaque niveau -->
<div class="@container">
  <div class="@container">
    <div class="@container">
      <div class="@sm:flex-row">
      </div>
    </div>
  </div>
</div>

<!-- Mieux : un seul @container utile -->
<div class="@container">
  <div>
    <div>
      <div class="@sm:flex-row">
      </div>
    </div>
  </div>
</div>

Ne pas sur-utiliser

Hero fixe en page d’accueil : media query suffit ; @container serait du bruit.

Règle : container query seulement si le composant vit dans des conteneurs de largeurs variées. Sinon, media query.

Débogage

DevTools → Elements → élément @container → Styles → règles @container → survol des breakpoints pour surligner le conteneur.

Computed → recherche container-type pour vérifier le statut.

Checklist

  1. Imbrication : 2–3 @container max
  2. Usage : réutilisation multi-contexte ; sinon media query
  3. Noms : sm/md/lg, pas mobile/tablet
  4. Sélecteurs : rester simples dans les blocs conteneur
  5. Animations : éviter de lier des animations à des changements fréquents de taille de conteneur

Testez dans des conteneurs étroits et larges — beaucoup de bugs n’apparaissent qu’après mise en prod.

Synthèse

Problème résolu : le composant s’adapte à son conteneur, pas seulement au viewport — vraie réutilisation.

Principe :

  • page → media queries (md:, lg:)
  • composants → container queries (@sm:, @lg:)

Perf : peu d’imbrication, pas d’usage systématique.

Un composant à réutiliser ? Commencez par une carte. Vous éviterez souvent de dupliquer des variantes par emplacement.

Pour aller plus loin : Container Queries (Tailwind) et CSS Container Queries (MDN).

Des questions ? La section commentaires est ouverte.

Composants responsive avec les container queries Tailwind

De zéro aux container queries Tailwind CSS pour adapter la mise en page au conteneur

⏱️ Estimated time: 30 min

  1. 1

    Step 1: Ajouter @container sur le parent

    Repérez le conteneur parent du composant à rendre responsive et ajoutez la classe `@container` :

    ```html
    <div class="@container">
    <!-- Les enfants peuvent utiliser les breakpoints conteneur -->
    </div>
    ```

    Cela indique au navigateur que cet élément est un conteneur de requête.
  2. 2

    Step 2: Appliquer les breakpoints conteneur sur les enfants

    Les enfants peuvent utiliser `@sm:`, `@md:`, `@lg:` et autres :

    ```html
    <div class="@container">
    <article class="flex flex-col @sm:flex-row @lg:gap-6">
    <!-- conteneur < 384px : disposition verticale -->
    <!-- conteneur >= 384px : disposition horizontale -->
    <!-- conteneur >= 512px : espacement accru -->
    </article>
    </div>
    ```

    Valeurs : @xs (320px), @sm (384px), @md (448px), @lg (512px), @xl (576px), etc.
  3. 3

    Step 3: Ajuster images et typographie

    Adaptez taille d'image et styles de texte à la largeur du conteneur :

    ```html
    <img class="w-full @sm:w-32 @lg:w-48 h-48 @sm:h-32 object-cover" />
    <p class="text-sm @lg:text-base line-clamp-2 @lg:line-clamp-3">
    ```

    Image pleine largeur dans un petit conteneur, 128px en moyen, 192px en grand.
  4. 4

    Step 4: Combiner media queries et container queries

    Mise en page de page en media query, composants en container query :

    ```html
    <!-- Page : media queries -->
    <div class="grid grid-cols-1 md:grid-cols-3 gap-6">
    <main class="md:col-span-2">
    <!-- Composant : container queries -->
    <div class="@container">
    <article class="flex flex-col @sm:flex-row">...</article>
    </div>
    </main>
    <aside class="@container">...</aside>
    </div>
    ```

    Chacun son rôle, sans mélanger les responsabilités.
  5. 5

    Step 5: Performance et débogage

    Points d'attention :

    • Imbriquez au plus 2-3 niveaux de `@container` pour limiter l'impact perf
    • Réservez les container queries aux composants réutilisables ; scènes fixes → media queries
    • Chrome DevTools : Elements → sélectionner le conteneur → panneau Styles, règles @container
    • Panneau Computed, recherche `container-type` pour confirmer le statut de conteneur

FAQ

Quelle différence entre container queries et media queries ?
Les media queries s'appuient sur la largeur du viewport (fenêtre du navigateur), idéal pour la mise en page globale. Les container queries s'appuient sur la largeur du conteneur parent, idéal pour les composants réutilisables. Le composant devient vraiment « portable » sans jeux de styles selon l'emplacement.
Quel support navigateur pour les container queries Tailwind ?
Les container queries ont été largement adoptées en 2023. En 2024, Chrome, Firefox, Safari et Edge les supportent ; couverture > 90 %. Pour d'anciens navigateurs, vérifiez les versions ciblées par votre audience.
Container query ou media query : quand choisir ?
Règle simple :

• Media queries : mise en page globale, navigation, zone Hero, éléments liés au viewport
• Container queries : composants réutilisables (cartes, lignes de liste), widgets de barre latérale, contenu de modale, composants imbriqués

En pratique, on combine souvent les deux : page en media query, composants en container query.
Les breakpoints conteneur Tailwind ont-ils les mêmes valeurs que les breakpoints viewport ?
Non. Les breakpoints conteneur sont plus petits, de 320px (@xs) à 1024px (@5xl). Les breakpoints viewport vont de 640px (sm) à 1536px (2xl). Un conteneur imbriqué ne dépasse pas le viewport : il faut des seuils plus fins.
Les container queries posent-elles un problème de performance ?
Légère surcharge, en général négligeable. Le risque vient surtout de la sur-imbrication : @container sur chaque item de liste avec plusieurs niveaux peut faire saccader le scroll. Limitez-vous à 2-3 niveaux et aux composants vraiment réutilisables.
Peut-on interroger la hauteur en container query ?
Pas pour l'instant. La spec CSS Container Queries ne couvre que la largeur (inline size). La hauteur est encore en discussion et non implémentée. Pour adapter selon la hauteur, il faut d'autres approches.
Comment déboguer les container queries dans Chrome DevTools ?
DevTools → Elements → élément avec @container → panneau Styles, règles @container → survol d'un breakpoint : Chrome met en évidence le conteneur.

Alternative : panneau Computed, recherche `container-type` pour confirmer le conteneur de requête.

9 min de lecture · Publié le: 27 mars 2026 · Mis à jour le: 27 juil. 2026

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog