Skip to Content
FrontendGrid & Flexbox

CSS Grid & Flexbox — Référence

Propriétés, modèles de positionnement et guide de décision pour les deux systèmes de mise en page CSS modernes.

Cette page est un complément à layout-patterns.mdx (motifs concrets) et à la section CSS de index.mdx (vue d’ensemble). Elle couvre les concepts avancés absents des deux pages.


Choisir Grid ou Flexbox

CritèreFlexboxGrid
Dimension principale1D (ligne OU colonne)2D (lignes ET colonnes simultanément)
Cas idéalBarres de navigation, boutons groupés, alignment interne d’un composantMise en page globale de page, carrousels, dashboards
Taille des itemsDétermine la taille du conteneurLe conteneur détermine la taille des items
Ordre visuelorder (facile)grid-area (précis)
Lignes nomméesNongrid-template-columns: [sidebar-start] 240px [sidebar-end] 1fr [main-end]
Sous-grilleNongrid-template-rows: subgrid

Règle pratique : utiliser Grid pour la structure globale de la page, Flexbox pour aligner les éléments à l’intérieur de chaque cellule ou composant.


Flexbox — Modèle d’axes

Flexbox manipule deux axes. Tout comprendre sur les axes évite 80 % des erreurs d’alignement.

→ flex-direction: row (par défaut) ┌─────────────────────────────────────────────┐ │ │ │ │ ←─ main-axis (axe principal) │ │ │ │ │ ↑ cross-axis │ └─────────────────────────────────────────────┘ ← flex-direction: row-reverse
Valeur flex-directionmain-axiscross-axis
row (défaut)horizontale ←→verticale ↑↓
row-reversehorizontale →←verticale ↑↓
columnverticale ↑↓horizontale ←→
column-reverseverticale ↓↑horizontale ←→

Alignement sur les axes

.container { display: flex; /* Axe principal (selon flex-direction) */ justify-content: center; /* center | flex-start | flex-end | space-between | space-around | space-evenly */ /* Axe perpendiculaire */ align-items: center; /* flex-start | center | flex-end | stretch | baseline */ /* Si wrap et que les lignes n'occupent pas toute la hauteur */ align-content: center; /* pareil que align-items, mais par LIGNE */ }

Piège : align-content n’a d’effet que si flex-wrap: wrap est activé et que les lignes n’occupent pas toute la hauteur du conteneur. Dans tous les autres cas, c’est align-items qui agit.

Alignement par item (align-self, justify-self)

Un item peut être aligné indépendamment des autres :

.item--top { align-self: flex-start; } .item--center { align-self: center; } .item--bottom { align-self: flex-end; } .item--stretch { align-self: stretch; }

Piège : align-self: stretch (valeur par défaut) pousse l’item à occuper toute la hauteur. Si l’item a height: auto, cette propriété est invisible. Donner une height explicite ou min-height révèle l’effet.

order — Ordonner sans toucher au HTML

.item--first { order: -1; } .item--second { order: 2; } /* L'ordre visuel ne change PAS l'ordre du DOM, ni la tabulation clavier */

Flex shorthand : décrypter flex: 1 1 200px

.flex-item { /* flex-grow | flex-shrink | flex-basis */ flex: 1 1 200px; }
ValeurSignification
flex: 11 1 0% — pousse à remplir l’espace restant, taille de base = 0
flex: 0 1 200pxNe grandit pas, peut rétrécir depuis 200px
flex: 0 0 200pxTaille fixe de 200px, ne grandit ni ne rétrécit
flex: none0 0 auto — taille intrinsèque, ne grandit ni ne rétrécit
flex: auto1 1 auto — grandit et rétrécit, taille de base = contenu

Piège : flex: 0 0 100% ne veut pas dire 100 % de la largeur. flex-basis: 100% est bien de 100 % du parent, mais si un item a flex: 0 0 100% et qu’il y en a 2, ils se déborderont mutuellement.


Grid — Concepts avancés

Grille implicite vs explicite

.container { display: grid; /* Grille EXPLICITE : les pistes sont déclarées */ grid-template-columns: 1fr 1fr 1fr; grid-template-rows: auto; /* Les items qui dépassent créent des pistes IMPLICITES */ }
Grille explicite 3×1 + 4 items ┌─────┬─────┬─────┐ │ 1 │ 2 │ 3 │ ← pistes explicites ├─────┤ │ │ │ 4 │ │ │ ← item 4 crée une 2e ligne implicite └─────┴─────┴─────┘

Piège : sans grid-template-rows déclaré, les lignes implicites prennent la hauteur minimale (auto). Un contenu long dans le 4e item déborde au-delà des 3 premières pistes. Fixer grid-auto-rows: 100px pour contrôler.

grid-template-areas avec mapping ASCII

.dashboard { display: grid; grid-template-columns: 240px 1fr 300px; grid-template-rows: auto 1fr auto; grid-template-areas: "sidebar header header" "sidebar main aside" "sidebar footer footer"; min-height: 100dvh; } .sidebar-nav { grid-area: sidebar; } .header { grid-area: header; } .main-content { grid-area: main; } .sidebar { grid-area: aside; } .footer { grid-area: footer; }

Piège : une zone nommée doit être un rectangle. On ne peut pas avoir une zone en L ou en T. Si une cellule reste vide, utiliser . (point) à la place du nom.

Positionnement avec des lignes nommées

.container { display: grid; grid-template-columns: [sidebar-start] 240px [sidebar-end content-start] 1fr [content-end]; grid-template-rows: [top] auto [mid] 1fr [bottom]; } .card--featured { /* Placer entre les lignes nommées */ grid-column: content-start / content-end; grid-row: mid / bottom; }

subgrid — Hériter des pistes du parent

.card-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; } .card { display: grid; grid-template-rows: subgrid; /* Hérite les lignes du parent */ row-gap: 0.5rem; } .card h2 { grid-row: 1; } .card p { grid-row: 2; } .card .meta{ grid-row: 3; } .card .img { grid-row: 4; }

Piège : subgrid hérite uniquement des pistes du parent dans la même direction. Utiliser grid-template-columns: subgrid et grid-template-rows: subgrid séparément.

grid-auto-flow

.container { display: grid; grid-template-columns: repeat(3, 1fr); /* default: row — remplit chaque ligne de gauche à droite */ grid-auto-flow: row; /* dense — remplit les trous, mais peut réordonner les items */ grid-auto-flow: row dense; /* column — remplit chaque colonne de haut en bas */ grid-auto-flow: column; /* diagonal — remplit diagonalement (rare) */ grid-auto-flow: diagonal; }

Auto-placement intelligent avec auto-rows / auto-columns

.container { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); grid-auto-rows: 100px; /* Taille des lignes créées dynamiquement */ gap: 1rem; }

Pièges Grid / Flexbox récurrents

PiègeSymptômeCorrection
align-items: stretch sur un item sans hauteurItem invisible ou coupéAjouter height: auto ou min-height
gap entre deux conteneurs imbriquésEspace inattendu au niveau de la borduregap agit entre les items, pas entre les conteneurs
flex-shrink: 0 + min-width conflictuelL’item refuse de rétrécir même avec overflow: hiddenDéfinir min-width: 0 sur l’item flex pour autoriser le rétrécissement
grid-auto-flow: dense réordonne les itemsUn item se retrouve à un endroit inattenduRetirer dense si l’ordre HTML doit être respecté
grid-area sans grid-template-areasLa zone est ignoréeDéclarer les zones dans grid-template-areas du parent
subgrid sur une grille sans lignes définiesErreur de rendu, les enfants sont empilésLe parent doit avoir grid-template-rows (ou -columns) déclaré
100% dans un item flex avec border-boxL’item déborde du conteneurUtiliser width: 0 et flex: 1 à la place de width: 100%
gap sur un item gridEspace créé entre l’item et le conteneurgap ne s’applique qu’au conteneur, pas à un item grid

Résumé rapide : quand utiliser quoi

Nouvelle mise en page ? ├─ Structure de page complète (header, nav, main, footer) ? │ → Grid ├─ Alignement horizontal/vertical simple (boutons, badges, icônes) ? │ → Flexbox ├─ Carrousel, tabs, filtres horizontaux ? │ → Flexbox ├─ Dashboard, grille de cartes responsive ? │ → Grid └─ Les deux ? → Grid pour la structure, Flexbox à l'intérieur de chaque cellule