Aller au contenu principal

Flexbox et Grid : arrêter de deviner

Une mise en page CSS finit souvent par tomber juste après six essais, sans qu'on sache lequel a marché. Cet article pose la règle qui sépare Flexbox de Grid en une question, explique la mécanique des deux axes, donne quatre mises en page complètes avec leur code, et liste les pièges qui coûtent le plus de temps aux personnes qui apprennent le CSS.

Guides & tutoriels ·
Adel LATIBI
Adel LATIBI

Le Briefing Dev - les ressources et actus de la semaine, droit dans ta boîte chaque vendredi gratuitement.

En vous inscrivant, vous acceptez de recevoir notre newsletter. Désinscription possible à tout moment.

Le CSS a cette particularité qu'on peut le pratiquer pendant des mois en obtenant des résultats corrects sans jamais avoir de modèle mental de ce qui se passe. Une div ne se centre pas, on ajoute display: flex, puis justify-content: center, ça ne bouge pas, on tente align-items: center, ça marche. On garde les deux au cas où, et on passe à la suite.

Cette méthode fonctionne un temps. Elle casse le jour où la maquette devient un peu dense, où un élément doit rester collé en bas d'une carte pendant que les autres cartes ont des hauteurs différentes, ou quand une grille de produits doit se réorganiser sans qu'on écrive dix media queries.

Flexbox et Grid ne sont pas deux versions du même outil, l'un moderne et l'autre plus moderne. Ce sont deux modèles de disposition qui répondent à deux questions différentes, et la plupart des blocages viennent d'avoir choisi celui qui ne correspondait pas à la question posée. Ce qui suit vise à te faire choisir avant d'écrire, pas après trois essais.

Le cycle du tâtonnement

Voici la forme que ça prend en pratique, sur une carte produit tout à fait banale. Titre, description de longueur variable, prix, bouton. La demande est simple : les boutons doivent s'aligner sur la même ligne en bas de chaque carte, même quand une description fait deux lignes et la suivante cinq.

La séquence habituelle commence par une hauteur fixe sur les cartes, ce qui tronque le texte le plus long. On passe à position: absolute sur le bouton, ce qui règle le problème visuellement et en crée un autre au premier redimensionnement. Puis on cherche sur Stack Overflow, on copie un bloc de dix lignes qui fonctionne, et on ne saura pas le reproduire la semaine suivante sur un cas voisin.

La réponse tient en une propriété appliquée au bon élément. Elle sera donnée plus bas, mais elle ne sert à rien tant que le raisonnement qui y mène n'est pas en place. Un extrait de code recopié règle un cas ; un modèle mental règle la famille de cas.

La question qui tranche entre Flexbox et Grid

Une seule question suffit à choisir dans la grande majorité des situations :

Dans le premier cas, c'est Flexbox. Le conteneur distribue l'espace disponible entre des éléments qui gardent leur mot à dire sur leur taille. Une barre de navigation, une liste de tags, un groupe de boutons, une ligne avec un logo à gauche et un menu à droite : le nombre d'éléments peut changer sans que le CSS bouge.

Dans le second, c'est Grid. Tu décris d'abord la structure, colonnes et lignes, puis tu y déposes le contenu. Une mise en page de page complète avec en-tête, barre latérale, contenu principal et pied de page, ou une galerie où toutes les vignettes doivent s'aligner en colonnes strictes : la trame existe indépendamment de ce qu'on met dedans.

Une autre formulation aide beaucoup les personnes en reconversion à qui j'enseigne le CSS : avec Flexbox, le contenu commande ; avec Grid, le conteneur commande. Quand tu hésites, demande-toi qui doit avoir le dernier mot sur les dimensions.

Flexbox : une direction, le contenu décide axe principal Grid : une trame définie avant le contenu colonnes et lignes fixées d'avance
Flexbox répartit sur un axe, Grid remplit une structure à deux dimensions.

Les deux modèles cohabitent sans problème dans une même page. Un layout Grid pour la structure générale, et à l'intérieur d'une cellule, un conteneur Flexbox pour aligner trois boutons : c'est la combinaison la plus courante sur un site réel, pas un compromis bancal.

Les deux axes, la source de la moitié des confusions

Pourquoi justify-content déplace parfois horizontalement, parfois verticalement ? Parce que ces propriétés ne parlent ni de gauche ni de haut. Elles parlent d'axes, et l'orientation des axes dépend d'une autre propriété.

Un conteneur flex a un axe principal, défini par flex-direction. Par défaut il vaut row, donc l'axe principal est horizontal. L'axe transversal est perpendiculaire, donc vertical. Passe en flex-direction: column et les deux axes pivotent, ce qui inverse le comportement des mêmes propriétés sans que tu les aies touchées.

La règle à retenir

  • justify-* agit sur l'axe principal
  • align-* agit sur l'axe transversal

En Grid, ces mêmes préfixes existent mais les axes ne bougent pas : justify-* concerne toujours les colonnes, align-* toujours les lignes. Et le suffixe indique la cible : -content déplace l'ensemble des pistes dans le conteneur, -items déplace chaque élément dans sa cellule, -self déplace un élément précis. Six propriétés, deux dimensions à combiner, plus rien à mémoriser au hasard.

Quatre mises en page, quatre décisions

La barre de navigation avec logo à gauche et menu à droite

Les éléments se suivent sur une ligne, leur largeur dépend de leur contenu. Flexbox.

.navbar {
  display: flex;
  align-items: center;      /* alignement vertical, axe transversal */
  justify-content: space-between;
  gap: 16px;
}

Aucune largeur n'est écrite. Ajoute un troisième bloc dans la barre, le CSS tient toujours.

La carte dont le bouton reste collé en bas

Le cas ouvert plus haut. La carte devient un conteneur flex en colonne, et une marge automatique absorbe tout l'espace restant au-dessus du bouton.

.card {
  display: flex;
  flex-direction: column;
  height: 100%;
}
 
.card__button {
  margin-top: auto;
}

Deux lignes utiles. En Flexbox, une marge auto mange l'espace libre de son côté, et cette mécanique remplace la plupart des positionnements absolus qu'on voit dans les projets de débutants.

La grille de cartes qui s'adapte sans media query

Une trame de colonnes régulières, avec un nombre de colonnes qui dépend de la place disponible. Grid, et un seul déclaration fait le travail.

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 24px;
}

Le navigateur calcule combien de colonnes de 280 pixels minimum tiennent dans la largeur, puis répartit le surplus grâce à 1fr. Quatre colonnes sur un écran large, une seule sur mobile, sans point de rupture écrit à la main.

La variante auto-fit se comporte pareil sauf quand il reste des colonnes vides : auto-fit les écrase et laisse le contenu s'étirer, auto-fill les conserve. Avec trois cartes sur un grand écran, auto-fit donne trois cartes très larges, auto-fill garde des cartes de taille normale alignées à gauche.

La structure de page en zones nommées

Ici la trame préexiste au contenu, et Grid permet de la dessiner en toutes lettres dans le CSS.

.layout {
  display: grid;
  grid-template-columns: 240px 1fr;
  grid-template-rows: auto 1fr auto;
  grid-template-areas:
    "header header"
    "aside  main"
    "footer footer";
  min-height: 100vh;
}
 
.layout > header { grid-area: header; }
.layout > aside  { grid-area: aside; }
.layout > main   { grid-area: main; }
.layout > footer { grid-area: footer; }
 
@media (max-width: 720px) {
  .layout {
    grid-template-columns: 1fr;
    grid-template-areas:
      "header"
      "main"
      "aside"
      "footer";
  }
}

La version mobile réordonne les zones sans toucher au HTML, et la barre latérale passe sous le contenu principal. Un détail à surveiller : cet écart entre l'ordre visuel et l'ordre du document se lit à la souris mais pas au clavier, puisque la tabulation suit le HTML. Sur un menu ou un formulaire, ça devient un problème d'accessibilité réel.

Les pièges qui font perdre des heures

Le texte qui refuse de se tronquer dans un conteneur flex

Un élément flex a par défaut min-width: auto, ce qui l'empêche de rétrécir en dessous de la largeur de son contenu. Résultat : un long titre pousse la carte hors du conteneur et text-overflow: ellipsis ne produit rien. Le correctif tient en une déclaration sur l'élément qui déborde : min-width: 0. Sur les projets que je reprends en dépannage, c'est de loin la ligne de CSS que j'ajoute le plus souvent.

Confondre width et flex-basis

Sur un élément flex, flex-basis prend le pas sur width quand l'axe principal est horizontal. Écrire les deux avec des valeurs différentes donne l'impression que la largeur est ignorée. Le raccourci flex: 1 vaut 1 1 0%, ce qui remet la base à zéro et fait que tous les éléments finissent à la même largeur, quel que soit leur contenu. Pour que le contenu reste pris en compte, la valeur est flex: 1 1 auto.

Utiliser Grid là où une ligne suffit

Une barre d'outils avec un nombre variable de boutons en Grid oblige à recompter les colonnes à chaque ajout. Le même besoin en Flexbox n'a rien à recompter. Cette erreur n'empêche rien de fonctionner, elle produit du CSS qu'il faut modifier à chaque évolution.

Attendre une hauteur qui n'existe pas

height: 100% demande à un élément d'occuper toute la hauteur de son parent, ce qui suppose que le parent en ait une définie. Si la chaîne est interrompue quelque part au-dessus, la valeur est ignorée en silence. Les unités 100vh ou 100dvh contournent le problème en se référant à la fenêtre, et dvh tient compte de la barre d'adresse qui se replie sur mobile.

Empiler des marges au lieu d'utiliser gap

La propriété gap fonctionne en Flexbox comme en Grid sur tous les navigateurs courants depuis plusieurs années. Les astuces à base de marge négative sur le conteneur pour compenser la marge du dernier élément appartiennent à une époque révolue, et elles cassent dès qu'un élément passe à la ligne.

Le réflexe qui règle la plupart de ces cas se prend avec les outils du navigateur. Dans l'inspecteur de Chrome ou Firefox, un badge flex ou grid apparaît à côté du conteneur ; en cliquant dessus, tu obtiens la visualisation des pistes, des numéros de ligne et des zones libres. Cette étape transforme le débogage CSS en lecture au lieu d'un jeu de devinettes, et elle rejoint ce qui est décrit dans l'article sur la méthode pour débugger sans paniquer.

Aller plus loin sur les bases

Ces mécaniques s'installent beaucoup plus vite en construisant des pages complètes qu'en lisant de la documentation. La formation HTML et CSS : créer sa première page web couvre la structure sémantique, le modèle de boîte, Flexbox et Grid sur des mises en page réelles. Elle fait partie de la catégorie Fondamentaux du catalogue LaPolaris, qui sert de socle avant d'attaquer un framework.

Un dernier point qui revient souvent chez les personnes en reconversion et les développeurs juniors : le CSS mis en page correctement ne remplace pas un HTML correct. Une grille visuellement impeccable construite sur une pile de div sans balises sémantiques reste difficile à naviguer au clavier et pauvre pour le référencement. Le choix entre Flexbox et Grid vient après la question de savoir ce que représente chaque bloc de la page.

Questions fréquentes

Faut-il apprendre Flexbox avant Grid ?

Oui, pour une raison pratique : Flexbox couvre les besoins les plus fréquents d'un projet débutant, et sa notion d'axe principal sert ensuite à comprendre les propriétés d'alignement de Grid, qui portent les mêmes noms. Compte quelques jours de pratique sur Flexbox avant d'aborder Grid.

Grid remplace-t-il Flexbox ?

Non. Les deux modèles sont maintenus en parallèle par le W3C et répondent à des besoins différents. Une page réelle utilise généralement Grid pour la structure globale et Flexbox à l'intérieur des blocs. Aucun des deux n'est prévu pour disparaître.

Comment centrer un élément horizontalement et verticalement ?

Sur le conteneur : display: grid; place-items: center;. La propriété place-items combine align-items et justify-items en une déclaration. La version Flexbox demande display: flex; align-items: center; justify-content: center; et donne le même résultat. Dans les deux cas, le conteneur doit avoir une hauteur pour que le centrage vertical ait un sens.

Est-ce que je peux abandonner Bootstrap grâce à Grid ?

Pour la partie mise en page, oui. Le système de colonnes de Bootstrap existait pour combler l'absence d'outil natif, ce qui n'est plus le cas. Bootstrap apporte aussi des composants prêts à l'emploi, boutons, modales, formulaires, et c'est ce reste qui justifie encore son usage sur certains projets.

Pourquoi mes colonnes ne font pas la largeur demandée ?

Deux causes reviennent presque toujours. Soit le padding et la bordure s'ajoutent à la largeur, ce que règle box-sizing: border-box appliqué globalement. Soit un contenu indivisible, image ou mot très long, impose un minimum, ce que règlent min-width: 0 sur l'élément et minmax(0, 1fr) sur la piste Grid.

Combien de temps pour être à l'aise avec les deux ?

En reproduisant des mises en page existantes plutôt qu'en lisant, deux à trois semaines de pratique régulière suffisent pour cesser de tâtonner. Le déclic vient en général après la troisième ou quatrième page refaite de zéro, quand tu choisis le modèle avant d'écrire la première ligne.

Une chose ne se règle pas avec un modèle mental : il faut avoir cassé quelques mises en page pour reconnaître les symptômes. Prends une page d'un site que tu aimes bien, ouvre l'inspecteur, et reconstruis-la sans regarder son CSS. Ce que tu n'arriveras pas à reproduire indiquera exactement ce qui te manque.

Pour la suite du parcours, l'article sur le choix entre front-end, back-end et fullstack aide à situer le CSS dans un parcours complet.

Vous êtes expert ?

Partagez votre expertise sur notre blog

Tutoriel, retour d'expérience, analyse - publiez un article invité et gagnez en visibilité.

Écrire pour nous