Skip to main content

Chapitre 29 : Arbitrage : Quand choisir Flexbox ou CSS Grid ?

Comparaison des cas d'usage unidimensionnels vs bidimensionnels pour optimiser la structure de mise en page.

L'un des débats les plus fréquents pour un développeur front-end est de savoir s'il doit utiliser Flexbox ou CSS Grid. Contrairement à une idée reçue, ces deux technologies ne sont pas concurrentes, mais complémentaires. Elles résolvent des problèmes de mise en page fondamentalement différents.

La Philosophie de Mise en Page

1. Quoi

Pour trancher entre Flexbox et Grid, il faut comprendre la distinction entre le Content-out (le contenu pilote la taille) et le Layout-in (la structure pilote le contenu).

  • Flexbox est un système de mise en page unidimensionnel. Il gère soit une ligne, soit une colonne à la fois. C'est un outil de distribution d'espace où les éléments s'adaptent à leur contenu. On parle d'approche Content-out.
  • CSS Grid est un système de mise en page bidimensionnel. Il gère simultanément les lignes et les colonnes. C'est un outil de définition de structure où le contenu est placé dans des cellules prédéfinies. On parle d'approche Layout-in.

2. Pourquoi

En milieu professionnel, choisir le mauvais outil entraîne souvent un code CSS "sale" :

  • Utiliser Grid pour aligner trois icônes dans un bouton est une sur-ingénierie qui complexifie la maintenance.
  • Utiliser Flexbox pour créer une grille complexe de dashboard avec des éléments qui s'étendent sur plusieurs lignes et colonnes mène à des hacks de width: 33.33% et des margin négatives fragiles.

L'arbitrage correct permet de réduire le nombre de lignes de CSS, d'améliorer les performances de rendu du navigateur et de faciliter le responsive design.

3. Comment

A. Syntaxe de base : Le rappel rapide

Flexbox (L'axe unique) :

.flex-container {
display: flex;
justify-content: space-between; /* Aligne sur l'axe principal */
align-items: center; /* Aligne sur l'axe secondaire */
}

CSS Grid (Le plan 2D) :

.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* Définit 3 colonnes égales */
grid-template-rows: auto 100px; /* Définit 2 lignes */
gap: 20px; /* Espace constant entre cellules */
}

B. Cas concret : Le Layout de Page Complet

Dans un projet réel, on combine les deux. On utilise Grid pour la structure globale (le "squelette") et Flexbox pour les composants internes (les "organes").

/* 1. Structure globale avec GRID (Layout-in) */
.page-layout {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 250px 1fr;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }

/* 2. Composants internes avec FLEXBOX (Content-out) */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1rem 2rem;
/* Ici, on ne se soucie pas de colonnes fixes,
on veut juste que le logo et le menu soient aux extrémités */
}

.nav-links {
/*
.nav-links est un enfant de .header, qui est lui-même une cellule Grid.
MAIS ici, on applique Flexbox à .nav-links pour gérer l'alignement
INTERNE de ses liens (1 seul axe horizontal → Flexbox).
C'est le pattern "Grid pour le squelette, Flexbox pour les organes" :
Grid pilote où se trouve .header dans la page,
Flexbox pilote comment les <li> s'organisent DANS .nav-links.
*/
display: flex;
gap: 1.5rem;
list-style: none;
}

C. Limitations

  • Flexbox : Devient ingérable dès que vous avez besoin que des éléments sur différentes lignes soient parfaitement alignés verticalement sans utiliser de largeurs fixes.
  • CSS Grid : Peut être trop rigide pour des éléments dont la taille doit varier dynamiquement selon le texte qu'ils contiennent sans affecter le reste de la grille.

4. Zone de Danger

L'erreur du "Tout-Grid" : Vouloir utiliser display: grid pour chaque petit alignement de texte ou d'icône. Cela rend le code verbeux et difficile à lire.

Bonne pratique : Si vous n'avez besoin de contrôler qu'un seul axe (horizontal OU vertical), utilisez Flexbox.

L'erreur du "Tout-Flex" : Créer des grilles de cartes (cards) en utilisant flex-wrap: wrap et des width: calc(33% - 20px).

Bonne pratique : Pour des grilles de cartes, utilisez grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)). C'est beaucoup plus robuste et ne nécessite aucun calcul manuel de marges.

Arbre de décision Flexbox vs Grid

Questions clés

1. Puis-je utiliser Flexbox à l'intérieur d'une cellule de CSS Grid ?

Découvrir la réponse

Oui, et c'est même recommandé. CSS Grid définit la position de la cellule dans la page, et Flexbox gère l'alignement du contenu à l'intérieur de cette cellule.

2. Quel système est le plus performant pour le navigateur ?

Découvrir la réponse

La différence est négligeable pour la majorité des sites. Cependant, CSS Grid peut être légèrement plus coûteux en calcul pour des grilles extrêmement complexes et dynamiques, mais il évite souvent l'utilisation de multiples div imbriquées nécessaires avec Flexbox, ce qui allège le DOM.

3. Comment gérer le responsive sans Media Queries avec Grid ?

Découvrir la réponse

En utilisant auto-fit ou auto-fill combiné avec minmax(). Cela permet à la grille de créer autant de colonnes que possible tant qu'elles respectent une taille minimale, sans avoir à redéfinir le nombre de colonnes manuellement.

4. Quand Flexbox est-il supérieur à Grid pour une grille de cartes ?

Découvrir la réponse

Lorsque vous voulez que la dernière ligne de cartes se centre ou s'étire de manière flexible si elle n'est pas complète. Grid force les éléments à rester dans leurs colonnes, tandis que Flexbox permet un alignement plus organique des éléments orphelins.

Mise en pratique

Exercice 1 : Reproduction guidée

Objectif : Créer une barre de navigation simple.

  • Un logo à gauche.
  • Un groupe de 3 liens centrés.
  • Un bouton "Connexion" à droite.
  • Les éléments doivent être parfaitement alignés verticalement.
Découvrir la solution commentée
.navbar {
display: flex;
/* Flexbox est idéal ici car on ne gère qu'un seul axe (horizontal) */
justify-content: space-between;
align-items: center;
padding: 0 20px;
height: 60px;
background: #f4f4f4;
/* border-box : le padding (0 20px) est inclus dans la hauteur/largeur déclarée.
height: 60px représente donc la hauteur totale visible, padding compris. */
box-sizing: border-box;
}

.nav-links {
display: flex;
/* Second niveau de flexbox pour aligner les liens entre eux */
gap: 20px;
list-style: none;
}

Exercice 2 : Adaptation

Objectif : Transformer une liste de cartes "Flex-wrap" en une grille "Auto-responsive".

HTML de départ :

<div class="card-container">
<div class="card">Carte 1</div>
<div class="card">Carte 2</div>
<div class="card">Carte 3</div>
<div class="card">Carte 4</div>
<div class="card">Carte 5</div>
</div>

CSS de départ (à adapter) :

.card-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
}

.card {
width: 30%;
border: 1px solid #ccc;
padding: 1rem;
background: #f9f9f9;
}

Modifiez .card-container pour utiliser CSS Grid afin que les cartes fassent au minimum 200px et au maximum 1fr, sans utiliser de Media Queries. Supprimez la propriété width sur .card.

Découvrir la solution commentée
.card-container {
display: grid;
/*
repeat(auto-fit, ...) : remplit l'espace disponible
minmax(200px, 1fr) : garantit que la carte ne descend pas sous 200px
mais prend tout l'espace restant si possible
*/
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
}

.card {
/* On retire les width: 30% car Grid gère maintenant la dimension */
border: 1px solid #ccc;
padding: 1rem;
}

Exercice 3 : Conception

Objectif : Concevoir un layout de "Portfolio" complexe.

  • Un Header qui prend toute la largeur.
  • Une section principale divisée en :
    • Une colonne latérale (sidebar) étroite.
    • Une zone de contenu principale.
  • À l'intérieur de la zone de contenu, une galerie d'images où certaines images prennent 2 colonnes de large et d'autres 1 seule.
  • Un Footer qui prend toute la largeur.
Découvrir la solution commentée
/* Structure globale : GRID */
.portfolio-container {
display: grid;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
grid-template-columns: 200px 1fr;
gap: 10px;
}

.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.footer { grid-area: footer; }

/* Zone de contenu : GRID imbriqué pour la galerie */
.content {
grid-area: content;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
}

/* Gestion des images spéciales */
.featured-image {
/* L'image s'étend sur 2 colonnes */
grid-column: span 2;
background: #ddd;
height: 200px;
}

.standard-image {
background: #eee;
height: 200px;
}

/* Le header peut utiliser FLEXBOX pour ses éléments internes */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background: #333;
color: white;
}