Grid & Flex, mieux ensemble que rivaux
Après avoir posé les bases dans notre précédent article CSS Grid et Flexbox se complètent parfaitement, nous poursuivons ici avec une approche plus approfondie. Grid et Flexbox ont bouleversé notre manière de structurer les pages web : ils sont devenus le socle d’une conception moderne, claire et adaptable. Les principes fondamentaux sont désormais bien établis et largement documentés ; place donc aux usages concrets et aux combinaisons plus fines.
Dans cet article, nous irons plus loin : comment associer Grid et Flex de façon complémentaire, construire des mises en page fluides sans multiplier les media queries, ou encore aligner et distribuer les éléments avec précision grâce aux propriétés modernes du CSS.
Grid + Flex : un duo indissociable
Pour comprendre l’apport de Grid et Flex, il est utile de revenir à un cas concret et familier. Imaginons une page web classique, structurée autour d’un en‑tête, d’une barre latérale, d’un contenu principal et d’un pied de page. On peut alors comparer les anciennes méthodes et voir ce que Grid et Flex apportent réellement :
<body>
<header>…</header>
<aside>…</aside>
<main>
<article>Article 1 (plein écran)</article>
<article>Article 2 (moitié)</article>
<article>Article 3 (moitié)</article>
</main>
<footer>…</footer>
</body>Première approche : mise en page par float
Historiquement, on utilisait les float pour positionner les éléments. La barre latérale était flottée à gauche, le contenu principal devait gérer des marges à droite, et les articles étaient contraints par des pourcentages et des clearfix. Le code devenait vite fragile et lourd à maintenir. Ajouter un article plus long, insérer une image trop large ou créer un nouveau bloc pouvait briser tout l’équilibre. Vous pouvez consulter le fichier de démonstration float.html, qui illustre cette approche et ses limites.
aside { float: left; width: 250px; }
main { margin-left: 250px; }
article { float: left; width: 50%; }Deuxième approche : mise en page avec Flex seul
Avec Flex, on a gagné en souplesse et en simplicité : les blocs principaux se disposent naturellement sans calculs de marges ou de largeurs. La structure générale se définit avec un conteneur unique qui répartit l’espace et adapte les éléments à la taille de l’écran.
body {
display: flex;
flex-wrap: wrap;
}
header, footer { flex: 1 1 100%; }
aside { flex: 0 0 250px; }
main { flex: 1; }Dans main, il devenait aussi possible de répartir les articles sans gérer manuellement les pourcentages, le moteur de rendu s’occupant de la distribution.
main {
display: flex;
flex-wrap: wrap;
}
main article:first-child { flex: 1 1 100%; }
main article { flex: 1 1 50%; }C’était déjà un progrès, mais on mélangeait structure globale et alignements internes, ce qui rendait la lecture du code moins claire et les ajustements moins évidents. Vous pouvez consulter le fichier de démonstration flex.html, qui montre cette organisation plus souple mais encore imparfaite.
Troisième approche : structurer avec Grid, organiser avec Flex
Avec Grid, on structure véritablement la page : il ne s’agit plus d’aligner des blocs, mais de définir un squelette complet et lisible. Grâce à grid-template-areas, chaque zone de la page prend sa place de manière explicite : header en haut, footer en bas, sidebar et contenu au centre. Le code devient presque une maquette visuelle : quelques lignes suffisent à décrire la structure. Plus besoin de marges calculées ni de positionnements hasardeux ; tout est clair, stable et évolutif.
body {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header"
"aside main"
"footer footer";
gap: 1rem;
}
header { grid-area: header; background: #e0f0ff; }
aside { grid-area: aside; background: #fce0e0; }
main { grid-area: main; background: #e0fce0; }
footer { grid-area: footer; background: #f0e0fc; }Ensuite, Flex prend le relais à l’intérieur des zones pour gérer la répartition des contenus. Concrètement, dans notre zone main, le premier article peut s’afficher sur toute la largeur tandis que les suivants se partagent automatiquement l’espace. Les ajustements sont gérés par le moteur de rendu, sans règles supplémentaires ni calculs fastidieux.
main {
display: flex;
flex-wrap: wrap;
gap: 1rem;
padding: 1rem; /* padding sur main, n'altère pas la structure */
}
main article {
padding: 0.5rem; /* padding interne pour distinguer les blocs enfants */
background: #fff8dc; /* couleur d’arrière-plan pour visualiser chaque bloc */
}
main article:first-child { flex: 1 1 100%; }
main article { flex: 1 1 50%; }Vous pouvez consulter le fichier de démonstration grid-flex.html, qui illustre cette combinaison et ses avantages.
Espacements et lisibilité : un changement d’approche
Autrefois, l’espacement entre les éléments dépendait quasi exclusivement de margin et padding. Chaque bloc imposait ses propres règles, ce qui pouvait casser la structure lorsqu’on modifiait un élément. Avec Grid et Flex, gap centralise cette gestion et rend le code plus lisible. Le padding, quant à lui, conserve un rôle interne : il crée une respiration à l’intérieur des composants, sans perturber l’alignement global.
Pourquoi cette association est-elle plus stable ?
- Lisibilité : Grid décrit la structure en quelques lignes, Flex gère l’intérieur avec précision.
- Souplesse :
gapévite les bricolages de marges et centralise les espacements.- Robustesse : on se débarrasse des flottants fragiles et des correctifs CSS coûteux.
- Évolutivité : la page peut évoluer sans réécrire toute la logique.
Grille fluide sans media queries
CSS Grid adapte automatiquement le nombre de colonnes à la largeur de l’écran. En combinant auto-fit, auto-fill et minmax(), le navigateur gère la mise en page sans media queries. à adapter le nombre de colonnes selon la largeur de l’écran, et cela, sans la moindre media query.
Imaginons une section d’actualités ou de cartes produits. Au lieu de fixer des breakpoints pour chaque format d’écran, on confie au moteur CSS le soin de déterminer combien de colonnes peuvent tenir confortablement dans la largeur. Ce comportement adaptatif réduit considérablement le code et améliore la lisibilité du style.
<section class="actualites">
<div class="card">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
<div class="card">Pellentesque habitant morbi tristique senectus et netus.</div>
<div class="card">Donec euismod, nisi vel tincidunt tincidunt.</div>
<div class="card">Sed ut perspiciatis unde omnis iste natus error sit.</div>
<div class="card">Ut enim ad minima veniam, quis nostrum exercitationem.</div>
<div class="card">Duis aute irure dolor in reprehenderit in voluptate velit.</div>
</section>Il est vrai que Flexbox, en combinant flex-wrap et des largeurs minimales (min-width), permettait déjà de simuler un comportement fluide sans recourir aux media queries. Le fichier de démonstration flex-autofit.html illustre ce comportement : les cartes s’adaptent tant que possible, mais les alignements et la gestion des sauts de ligne restent perfectibles.
.actualites {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.card {
min-width: 200px;
flex: 1 1 200px;
background: #fff8dc;
padding: 1rem;
border-radius: 6px;
text-align: center;
}
Chaque ligne de flex agit indépendamment des autres : si la première ligne contient quatre cartes, elles s’étirent sur environ 25% chacune, mais si la suivante n’en contient que deux, elles prennent chacune 50% de la largeur. Résultat : les colonnes ne sont plus alignées horizontalement, créant un effet visuel désordonné. Ce comportement est dû à la répartition automatique de l’espace dans Flexbox, ligne par ligne, sans grille fixe en arrière-plan.
Là où Flex répartit ligne par ligne, Grid raisonne en structure complète, le contrôle est plus structurant : on travaille directement en colonnes explicites, avec un alignement parfait, une distribution régulière et des sauts de ligne cohérents. Le trio auto-fit, auto-fill et minmax() simplifie donc la logique, en laissant le navigateur orchestrer la mise en page selon l’espace disponible.
.actualites {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.card {
background: #fff8dc;
padding: 1rem;
border-radius: 6px;
text-align: center;
}
Le paramètre minmax(200px, 1fr) garantit qu’une carte ne fera jamais moins de 200px, mais qu’elle peut s’étendre lorsque l’espace le permet. La grille s’adapte donc automatiquement, passant de une à plusieurs colonnes selon la largeur disponible. Le mot-clé auto-fit remplit l’espace avec des colonnes vides si nécessaire, tandis que auto-fill conserve les colonnes, même invisibles. Vous pouvez consulter la démonstration grid-autofit.html pour visualiser ce comportement en temps réel et mieux percevoir la nuance entre auto-fit et auto-fill.
Gérer les espacements avec gap et space-evenly
Avant l’arrivée de gap et de space-evenly, espacer correctement les éléments relevait du casse-tête. On empilait les marges, on jouait avec des :last-child ou on glissait des blocs vides pour rééquilibrer les alignements. Ces bricolages rendaient le code fragile, difficile à maintenir et peu fiable sur des contenus dynamiques ou responsifs.
Désormais, les propriétés modernes comme gap (utilisable aussi bien en Flex qu’en Grid) et justify-content: space-evenly permettent d’obtenir des espacements réguliers, sans artifice ni ajustement manuel. Le résultat est plus stable, plus lisible, et reste cohérent quelle que soit la taille de l’écran.
Prenons un exemple concret : une barre de navigation horizontale ou un groupe de boutons d’action. Avec ces propriétés, quelques lignes suffisent pour obtenir une mise en page fluide et équilibrée.
<nav class="menu">
<a href="#">Accueil</a>
<a href="#">Projets</a>
<a href="#">Blog</a>
<a href="#">Contact</a>
</nav>Ce principe fonctionne aussi bien avec une structure en flex qu’en grid, avec quelques nuances. En flex, la répartition horizontale est naturelle et bien gérée via justify-content, mais la disposition verticale reste limitée. En grid, on peut agir dans les deux dimensions, ce qui rend gap encore plus puissant pour des interfaces complexes.
/* --- Menu horizontal en flex --- */
.menu {
display: flex;
justify-content: space-evenly;
gap: 1rem; /* Ajoute un espacement constant entre les liens */
}
.menu a {
padding: 0.5rem 1rem;
background: #e0f0ff;
border-radius: 4px;
text-decoration: none;
}
/* --- Variante en grid, utile pour un menu vertical ou responsive --- */
.menu-grid {
display: grid;
gap: 1rem;
justify-items: center; /* Centrer chaque lien */
}
.menu-grid a {
padding: 0.5rem 1rem;
background: #e0f0ff;
border-radius: 4px;
text-decoration: none;
}Résultat : les liens sont parfaitement répartis, sans calculs compliqués. space-evenly répartit l’espace disponible entre tous les éléments et aux extrémités, contrairement à space-between ou space-around. Le gap, lui, peut être combiné pour ajouter une séparation minimale cohérente. Rapprochez vous de la démonstration complète dans gap-spaceevenly.html.
Grilles asymétriques et superpositions
Il n’est pas nécessaire qu’une grille soit régulière ou homogène. Avec grid-area, nous pouvons positionner chaque élément à un endroit précis de la grille, parfois sur plusieurs colonnes ou lignes. En ajoutant z-index, nous introduisons la notion de superposition, ce qui permet de croiser les blocs et de superposer images et textes comme dans une mise en page de magazine.
<div class="grid-mag">
<div class="visuel"></div>
<div class="texte">
<h2>Une mise en page visuelle</h2>
<p>Ce bloc de texte se superpose légèrement au visuel. Il hérite de la même ligne de grille mais se place par-dessus grâce au z-index.</p>
</div>
<div class="carte">
<h3>Carte 1</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
<div class="carte">
<h3>Carte 2</h3>
<p>Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
<div class="carte">
<h3>Carte 3</h3>
<p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.</p>
</div>
</div>Cette approche permet de garder une structure HTML simple tout en créant des compositions visuelles riches. Plus besoin de positionnements absolus ni de marges négatives pour obtenir des effets de superposition.
Imaginons une page d’accueil avec une grande image en bandeau occupant toute la largeur. Un bloc de texte peut venir partiellement la recouvrir grâce à grid-area et z-index. Plus bas, des cartes ou des boutons s’alignent librement, sans contrainte de symétrie. Cette mise en page, inspirée des magazines imprimés, joue sur les chevauchements pour guider le regard sans rompre l’équilibre visuel.

Les blocs peuvent être nommés dans le CSS pour plus de lisibilité, mais le HTML reste plat tandis que le rendu visuel est entièrement dicté par le CSS avec grid-template-areas pour plus de lisibilité, ou bien positionnés directement avec grid-column et grid-row. L’important est de bien comprendre que ce n’est pas le HTML qui dicte la position, mais le CSS, voir grid-overlap-magazine.html.
Alignement des boutons : Flex ou Grid ?
Problème classique : aligner les boutons en bas Lorsqu’on présente une série de cartes produits avec des descriptions plus ou moins longues, un souci d’alignement esthétique apparaît rapidement : les boutons “Acheter” se retrouvent à des hauteurs différentes. Ce déséquilibre visuel nuit à la lisibilité et donne une impression de mise en page approximative. Pour résoudre cela, on cherche à forcer chaque carte à occuper la même hauteur, et à aligner le bouton en bas, quel que soit le contenu.

Solution côté Flexbox Avec display: flex appliqué sur le conteneur .catalogue, chaque carte .produit peut s’étirer verticalement grâce à align-items: stretch. À l’intérieur de chaque carte, un margin-top: auto placé sur le bouton permet de le repousser vers le bas, en occupant tout l’espace disponible au-dessus.
Solution côté Grid Comme avec Flex, cette approche répartit l’espace de façon équilibrée tout en offrant une structure plus explicite. Le conteneur .catalogue est défini en display: grid avec un nombre de colonnes fixe, et chaque carte .produit conserve la même hauteur grâce à l’alignement implicite des lignes. Le bouton placé à l’intérieur est repoussé vers le bas avec margin-top: auto, pour un rendu régulier et harmonieux.
Comparaison Flex vs Grid Dans ce scénario, les deux solutions sont valables et produisent un rendu quasi identique. Grid offre un peu plus de contrôle sur la disposition générale (colonnes fixes, alignements précis), tandis que Flex est souvent plus rapide à mettre en place dans des cas simples. L’important reste que la structure interne de la carte permette de pousser les éléments du bas, et donc que le bouton soit logé en dernier dans une carte structurée verticalement, voir flex-grid-hauteur-cartes.html.
Alignements fins avec place-items et justify-self
Parfois, on ne cherche pas à répartir un ensemble d’éléments dans une grille, mais à ajuster précisément un seul d’entre eux. C’est là que des propriétés comme place-items, align-self ou justify-self prennent tout leur sens. Elles permettent d’aligner finement un bloc sans affecter les autres, exactement ce qu’on cherche lorsqu’un bouton ou une image doit se placer en bas à droite d’une carte, sans perturber la structure globale.

Dans une grille de fiches produit, par exemple, chaque carte suit le même gabarit. Mais si l’une d’entre elles propose un bouton d’action (commande, téléchargement, partage…), il peut être souhaitable de l’aligner tout en bas, à droite, et ce sans influencer la disposition du contenu texte ou image. Un simple justify-self: end et align-self: end suffisent alors à le repositionner proprement dans sa cellule, sans recourir à des marges manuelles ni à un display: flex de secours, voir grid-self-align.html.
Ces propriétés (
justify-self,align-self,place-items) sont propres à CSS Grid. En contexte Flexbox, on doit souvent recourir à des astuces commemargin-left: autopour aligner un élément, mais cela n’offre pas le même niveau de contrôle cellulaire.
Debug & performances
Pour repérer les structures de grille ou les décalages inattendus, rien de plus efficace que d’ajouter temporairement un outline ou un background léger sur les zones. Cela s’avère très utile lorsqu’on travaille sur un tableau de bord multi-sections, une page produit avec sidebar ou une home composée de blocs thématiques.
.debug-grid {
outline: 1px dashed #888;
background: rgba(240, 240, 255, 0.3);
}On peut aussi s’aider de grid-template-areas pour nommer visuellement les zones : même en version temporaire, cette approche aide à mieux comprendre comment s’articulent les éléments dans un layout complexe.
.debug-areas {
display: grid;
grid-template-areas:
"header header"
"aside main"
"footer footer";
gap: 1rem;
}
.debug-areas > * {
outline: 1px dotted #999;
background: rgba(200, 200, 255, 0.15);
}Ces noms servent de repères visuels pour relier directement le code à la maquette mentale du site, ce qui est particulièrement utile en phase de prototypage ou de refactorisation.
Côté fluidité, les propriétés contain: layout; et will-change: transform; peuvent vraiment faire la différence quand une section du site est mise à jour très fréquemment. Par exemple, sur un tableau de bord avec graphiques animés ou listes qui défilent automatiquement, elles permettent au navigateur d’optimiser le rendu en isolant ces zones du reste du layout. Cela évite des recalculs de style ou de positionnement inutiles à chaque changement de contenu.
.stats-panel {
contain: layout;
will-change: transform;
}Ces propriétés sont particulièrement utiles lorsqu’un composant dynamique est intégré à une structure grid ou flex. Prenons un tableau de bord composé de graphiques régulièrement mis à jour : à chaque animation ou variation de contenu, le navigateur doit recalculer la disposition, parfois même au niveau de l’ensemble de la grille ou de la ligne flex, voir flex-grid-debug.html.
Avec contain: layout;, on isole visuellement et structurellement le composant : le navigateur considère qu’il n’a aucun impact sur les éléments voisins. Et avec will-change: transform;, on lui donne un indice pour qu’il prépare une optimisation graphique (allocation de mémoire, calque dédié, etc.). En pratique, cela évite que les changements fréquents d’un panneau viennent perturber les autres contenus autour. C’est donc une aide précieuse dans des interfaces denses, animées, ou fortement réactives comme les dashboards, les widgets de statistiques ou les carrousels intelligents.
Conclusion
Au fil des cas concrets, une évidence s’impose : il ne s’agit pas de choisir entre Grid et Flex, mais de comprendre ce que chacun sait faire de mieux. Grid pose les repères structurels, Flex ajuste localement les contenus. Grid organise, Flex distribue. L’un crée l’espace, l’autre le remplit. Ce duo, bien exploité, permet de construire des interfaces claires, adaptables et maintenables.
Quelques réflexes suffisent à gagner en lisibilité : utiliser gap plutôt que des marges, préférer minmax(0, 1fr) pour éviter les débordements, recourir à margin-top: auto pour fixer un pied de carte, ou activer temporairement des classes de débogage pour mieux comprendre une structure. Et si certaines limites subsistent dans les grilles imbriquées, CSS continue d’évoluer : nous consacrerons bientôt un article à subgrid, qui permet à un enfant d’hériter de la grille de son parent. Alignement garanti, sans duplication.
