Skip to main content

Chapitre 28 : Alignement et espacement avancé dans Grid et Flexbox

Concepts clés : gap, align-content, justify-self

L'alignement et l'espacement sont les piliers d'une interface utilisateur professionnelle. Si les bases de Flexbox et Grid permettent de positionner des éléments, la maîtrise des propriétés avancées d'alignement et de distribution d'espace permet de passer d'une mise en page "qui fonctionne" à une mise en page "pixel-perfect" et adaptable.

Ce chapitre explore la gestion fine des espaces vides et le positionnement individuel des éléments au sein de leurs conteneurs.

La propriété Gap

1. Quoi

La propriété gap (anciennement grid-gap pour Grid) définit l'espacement constant entre les lignes et les colonnes d'un conteneur Flexbox ou Grid. Contrairement aux marges (margin), le gap ne s'applique qu'entre les éléments, et non sur les bords extérieurs du conteneur.

Elle se décompose en deux propriétés spécifiques :

  • row-gap : L'espace vertical entre les lignes.
  • column-gap : L'espace horizontal entre les colonnes.

2. Pourquoi

L'utilisation des marges pour créer de l'espace entre des éléments (le pattern margin-right ou margin-bottom) crée souvent des problèmes de "bordure" : le dernier élément de la ligne possède une marge inutile qui décale l'alignement global ou nécessite l'utilisation de sélecteurs complexes comme :last-child { margin-right: 0; }.

gap résout ce problème nativement en ignorant les bords extérieurs, simplifiant ainsi radicalement le CSS et rendant le design plus robuste lors du passage en mode responsive.

3. Comment

A. Syntaxe de base

.container {
display: grid; /* ou flex */
gap: 20px; /* Applique 20px verticalement et horizontalement */
}

.container-specific {
display: grid;
row-gap: 10px;
column-gap: 30px;
}

B. Cas concret : Grille de cartes de produits

Dans un catalogue e-commerce, on souhaite un espacement régulier entre les cartes, tout en gardant un contrôle strict sur le padding du conteneur parent.

.product-grid {
display: grid;
/* Création de colonnes adaptatives avec un minimum de 250px */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));

/* Espacement constant entre les cartes */
gap: 2rem;

/* Le padding gère l'espace extérieur, le gap gère l'espace intérieur */
padding: 2rem;
background-color: #f5f5f5;
}

.product-card {
background: white;
padding: 1rem;
border-radius: 8px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

C. Limitations

  • Compatibilité Flexbox : Bien que gap soit désormais largement supporté dans Flexbox (Safari 14.1+), certains très vieux navigateurs ne le gèrent que pour Grid.
  • Interaction avec margin: auto : Si un élément possède margin: auto, il peut "pousser" et ignorer visuellement l'effet du gap en occupant tout l'espace disponible.

4. Zone de Danger

Erreur commune : Utiliser margin sur tous les enfants pour créer de l'espace.

/* MAUVAIS : crée un décalage sur le bord droit et bas */
.item {
margin: 10px;
}

Bonne pratique : Utiliser gap sur le parent.

/* BIEN : espace uniquement l'intérieur */
.container {
display: flex;
gap: 10px;
}

Alignement du contenu : align-content

1. Quoi

align-content définit l'alignement des lignes de contenu sur l'axe transverse (axe vertical en flex-direction: row).

Attention cruciale : Cette propriété n'a d'effet que si :

  1. Le conteneur a une hauteur définie (ou une hauteur minimale).
  2. Le contenu "wrap" (est réparti sur plusieurs lignes) via flex-wrap: wrap ou s'il s'agit d'une grille CSS.

2. Pourquoi

Alors que align-items aligne les éléments à l'intérieur de leur ligne respective, align-content aligne le bloc entier de lignes par rapport au conteneur. C'est l'outil indispensable pour centrer verticalement un groupe de lignes ou les répartir uniformément dans un espace disponible.

3. Comment

A. Syntaxe de base

.container {
display: flex;
flex-wrap: wrap;
height: 500px;
align-content: center; /* Centre tout le bloc de lignes verticalement */
}

B. Cas concret : Galerie d'images centrée

Imaginez une galerie où le nombre d'images varie. Vous voulez que, peu importe le nombre de lignes créées, le bloc global soit centré verticalement dans la section.

.gallery-section {
display: flex;
flex-wrap: wrap;
gap: 1rem;

/* On définit une hauteur pour voir l'effet de align-content */
min-height: 80vh;

/* Répartit les lignes uniformément avec un espace entre elles */
align-content: space-around;

justify-content: center; /* Centre horizontalement */
}

.gallery-item {
flex: 0 1 200px;
height: 150px;
background: #ddd;
}

C. Limitations

  • Ligne unique : Si vous n'avez qu'une seule ligne d'éléments (pas de wrap), align-content ne fera absolument rien. Utilisez align-items dans ce cas.

4. Zone de Danger

Confusion align-items vs align-content : Essayer de centrer verticalement un bloc de plusieurs lignes avec align-items: center. Cela centrera chaque élément dans sa ligne, mais les lignes resteront collées en haut du conteneur.

Bonne pratique :

  • align-items → Alignement interne à la ligne.
  • align-content → Alignement du groupe de lignes.

Différence align-items vs align-content


Alignement individuel : justify-self

1. Quoi

justify-self permet à un élément individuel de modifier son alignement sur l'axe principal (horizontal en Grid).

Note fondamentale : justify-self ne fonctionne pas en Flexbox. En Flexbox, l'alignement horizontal individuel se gère via margin: auto. En Grid, justify-self est pleinement opérationnel.

2. Pourquoi

Dans une grille, on veut souvent que la majorité des éléments occupent tout l'espace de leur cellule, mais qu'un élément spécifique (comme un bouton "Supprimer" ou un badge) soit aligné à droite ou au centre de sa propre cellule sans affecter les autres.

3. Comment

A. Syntaxe de base (Grid uniquement)

.grid-item {
justify-self: end; /* Aligne l'élément à la fin de sa cellule (droite) */
}

B. Cas concret : Tableau de bord administratif

Création d'une ligne de tableau en Grid où le nom est à gauche, le statut au centre, et l'action à droite.

.admin-row {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: 1rem;
align-items: center;
padding: 1rem;
border-bottom: 1px solid #eee;
}

.user-name {
justify-self: start; /* Aligné à gauche */
font-weight: bold;
}

.user-status {
justify-self: center; /* Aligné au centre de sa colonne */
font-size: 0.8rem;
}

.user-action {
justify-self: end; /* Aligné à droite de sa colonne */
}

C. Limitations

  • Flexbox : Comme mentionné, justify-self est ignoré en Flexbox. Pour obtenir le même effet, utilisez margin-left: auto sur l'élément pour le pousser vers la droite.

4. Zone de Danger

Erreur commune : Tenter d'utiliser justify-self dans un conteneur display: flex.

.flex-item {
display: flex;
justify-self: end; /* ❌ NE FONCTIONNE PAS */
}

Bonne pratique :

  • En Grid → justify-self: end.
  • En Flexbox → margin-left: auto.

Questions clés

1. Quelle est la différence fondamentale entre gap et margin ?

Découvrir la réponse

Le gap définit l'espace entre les éléments d'un conteneur Flex ou Grid, sans ajouter d'espace sur les bords extérieurs du conteneur. La margin s'ajoute autour de chaque élément, ce qui crée souvent des espaces indésirables sur les bords du parent, nécessitant des corrections manuelles.

2. Pourquoi align-content semble-t-il ne pas fonctionner dans mon conteneur Flexbox ?

Découvrir la réponse

Il y a généralement deux raisons possibles :

  • Soit vous n'avez pas défini de hauteur (height ou min-height) pour le conteneur, donc celui-ci s'adapte exactement à la taille du contenu, laissant aucun espace vide à distribuer.
  • Soit vous n'avez pas activé flex-wrap: wrap. align-content ne s'applique qu'aux conteneurs multi-lignes.

3. Comment aligner un seul élément à droite dans une ligne Flexbox ?

Découvrir la réponse

Puisque justify-self ne fonctionne pas en Flexbox, la méthode idiomatique consiste à appliquer margin-left: auto à l'élément concerné. Cela forcera l'élément à consommer tout l'espace disponible à sa gauche, le poussant ainsi vers la droite.

4. Quelle propriété utiliser pour centrer verticalement un élément unique dans une cellule Grid ?

Découvrir la réponse

Pour l'alignement vertical (axe transverse) d'un seul élément, on utilise align-self: center. Pour l'alignement horizontal (axe principal) dans la cellule, on utilise justify-self: center.


Mise en pratique

Exercice 1 : Reproduction guidée

Objectif : Créer une grille de 3x3 cartes avec un espacement constant.

  • Créez un conteneur .grid-container avec display: grid.
  • Définissez 3 colonnes égales.
  • Appliquez un espacement de 25px entre toutes les cartes en utilisant une seule propriété.
  • Ajoutez un padding de 20px au conteneur pour éviter que les cartes ne collent aux bords de la page.
Découvrir la solution commentée
.grid-container {
display: grid;
/* 3 colonnes égales */
grid-template-columns: repeat(3, 1fr);

/* Utilisation de gap pour l'espacement interne uniquement */
gap: 25px;

/* Padding pour l'espace extérieur */
padding: 20px;
}

.card {
background: #eee;
height: 100px;
border: 1px solid #ccc;
}

Exercice 2 : Adaptation

Objectif : Gérer un alignement vertical complexe.

  • Créez un conteneur Flexbox de 600px de hauteur.
  • Ajoutez 6 éléments enfants (divs) avec une largeur de 200px et une hauteur de 100px.
  • Activez le wrap.
  • Faites en sorte que les lignes de cartes soient regroupées et centrées verticalement au milieu du conteneur, tout en gardant un espace de 20px entre chaque carte.
Découvrir la solution commentée
.container {
display: flex;
flex-wrap: wrap; /* Obligatoire pour align-content */
height: 600px;

/* Centre le bloc de lignes verticalement */
align-content: center;

/* Espacement entre les éléments */
gap: 20px;

border: 2px solid black;
}

.item {
width: 200px;
height: 100px;
background: lightblue;
}

Exercice 3 : Conception

Objectif : Créer un header de navigation "Hybrid Grid".

  • Créez un header avec display: grid et 3 colonnes : [Logo] [Menu] [Actions].
  • Le Logo doit être aligné à gauche (start).
  • Le Menu doit être centré horizontalement dans sa cellule.
  • Le bloc Actions doit être aligné à droite (end).
  • Tous les éléments doivent être centrés verticalement.
  • Ajoutez un espacement de 1.5rem entre les colonnes.
Découvrir la solution commentée
.header {
display: grid;
/* Logo prend l'espace nécessaire, Menu prend le reste, Actions l'espace nécessaire */
grid-template-columns: auto 1fr auto;

/* Alignement vertical global pour tous les enfants */
align-items: center;

/* Espacement entre colonnes */
gap: 1.5rem;

padding: 1rem 2rem;
background: #333;
color: white;
}

.logo {
justify-self: start; /* Aligné à gauche de sa cellule */
}

.menu {
justify-self: center; /* Centré dans sa cellule */
display: flex;
gap: 1rem;
}

.actions {
justify-self: end; /* Aligné à droite de sa cellule */
}