Chapitre 26 : Placement explicite dans la grille CSS
Concepts clés : grid-column, grid-row, grid-area
Dans le chapitre précédent, nous avons appris à définir la structure d'une grille (le "squelette"). Par défaut, le navigateur place les éléments les uns après les autres selon l'ordre du HTML (placement automatique). Cependant, pour créer des mises en page complexes — comme un tableau de bord ou un magazine numérique — nous devons pouvoir dire précisément à un élément : "Toi, commence à la colonne 2 et termine à la colonne 4".
C'est ce qu'on appelle le placement explicite.
Le positionnement par lignes
1. Quoi
Le positionnement par lignes consiste à définir les limites d'un élément en utilisant les lignes de grille (grid lines). Contrairement à une idée reçue, on ne positionne pas un élément "dans la cellule 1", mais "entre la ligne 1 et la ligne 2".
Les propriétés fondamentales sont :
grid-column-start/grid-column-end: Définit les bornes verticales.grid-row-start/grid-row-end: Définit les bornes horizontales.
Pour plus de concision, CSS propose des propriétés raccourcies (shorthands) :
grid-column: Raccourci pourstart/end.grid-row: Raccourci pourstart/end.
2. Pourquoi
Le placement explicite est indispensable dès que l'ordre visuel ne correspond pas à l'ordre du DOM (Document Object Model).
Dans un projet professionnel, cela permet :
- De créer des superpositions d'éléments (plusieurs éléments occupant la même zone).
- De gérer des mises en page asymétriques sans multiplier les
divimbriquées. - De modifier radicalement la structure d'une page via des Media Queries sans toucher au HTML.
3. Comment
A. Syntaxe de base
La syntaxe utilise le slash / pour séparer le point de départ et le point d'arrivée.
.item {
/* Commence à la ligne 1, s'arrête à la ligne 3 (occupe 2 colonnes) */
grid-column: 1 / 3;
/* Commence à la ligne 2, s'arrête à la ligne 4 (occupe 2 lignes) */
grid-row: 2 / 4;
}
B. Cas concret : Mise en page de Dashboard
Voici une implémentation robuste pour un layout de type administration.
.dashboard-container {
display: grid;
/* 3 colonnes : sidebar fixe, contenu flexible, panneau latéral */
grid-template-columns: 250px 1fr 300px;
/* 3 lignes : header, contenu principal, footer */
grid-template-rows: 60px 1fr 40px;
height: 100vh;
gap: 1rem;
}
.sidebar {
/* Occupe la colonne 1 et s'étend de la ligne 1 à 3 (toute la hauteur) */
grid-column: 1 / 2;
grid-row: 1 / 4;
background-color: #2c3e50;
}
.header {
/* Occupe les colonnes 2 et 3, sur la première ligne */
grid-column: 2 / 4;
grid-row: 1 / 2;
background-color: #ecf0f1;
}
.main-content {
/* Occupe la colonne centrale, ligne 2 */
grid-column: 2 / 3;
grid-row: 2 / 3;
}
.right-panel {
/* Occupe la colonne 3, ligne 2 */
grid-column: 3 / 4;
grid-row: 2 / 3;
}
.footer {
/* Occupe colonnes 2 et 3, dernière ligne */
grid-column: 2 / 4;
grid-row: 3 / 4;
}
C. Limitations et astuces
- Le mot-clé
span: Au lieu de calculer la ligne de fin, on peut indiquer combien de cellules l'élément doit traverser.grid-column: 1 / span 2;(Commence à 1 et s'étend sur 2 colonnes).
- Lignes négatives :
-1représente toujours la dernière ligne de la grille, quelle que soit sa taille.grid-column: 1 / -1;(L'élément occupe toute la largeur de la grille).
- Dépassement : Si vous placez un élément sur une ligne qui n'existe pas encore (ex:
grid-column: 1 / 10dans une grille de 3 colonnes), CSS Grid créera des colonnes implicites pour accommoder l'élément.
4. Zone de Danger
❌ Erreur commune : Confondre l'index de la cellule et l'index de la ligne.
Exemple : Pour occuper la première cellule, on écrit 1 / 2 et non 1 / 1 (car 1 / 1 signifie que l'élément commence et s'arrête à la même ligne, donc il a une largeur de 0).
✅ Bonne pratique : Utiliser span pour les éléments dont la largeur est fixe en nombre de colonnes, et les indices négatifs (-1) pour les éléments qui doivent toujours toucher le bord droit/bas.
Système de numérotation des lignes CSS Grid
Le positionnement par zones nommées
1. Quoi
Le positionnement par zones est une abstraction sémantique du placement par lignes. Au lieu de manipuler des chiffres, on donne des noms aux zones de la grille via grid-template-areas sur le container, puis on assigne l'élément à cette zone via grid-area sur l'item.
2. Pourquoi
C'est la méthode la plus lisible et la plus maintenable pour les layouts de page entiers. Elle permet de "dessiner" la structure de la page directement dans le CSS. C'est extrêmement puissant pour le responsive design : on peut changer totalement la disposition des zones dans une media query sans modifier une seule ligne de code sur les éléments enfants.
3. Comment
A. Syntaxe de base
.container {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }
B. Cas concret : Layout Adaptatif (Desktop vs Mobile)
.page-layout {
display: grid;
gap: 10px;
/* Mobile par défaut : tout est empilé */
grid-template-areas:
"nav"
"content"
"aside"
"footer";
grid-template-columns: 1fr;
}
/* Desktop : Disposition complexe */
@media (min-width: 768px) {
.page-layout {
grid-template-columns: 200px 1fr 200px;
grid-template-areas:
"nav nav nav"
"nav content aside"
"footer footer footer";
}
}
.main-nav { grid-area: nav; }
.main-content { grid-area: content; }
.sidebar { grid-area: aside; }
.main-footer { grid-area: footer; }
C. Limitations
- Rectangles uniquement : Une zone nommée doit impérativement former un rectangle. Vous ne pouvez pas créer de zones en forme de "L" ou de "T".
- Nommage : Si une cellule ne doit contenir aucun élément, on utilise le point
.dansgrid-template-areas. - Syntaxe stricte : Chaque ligne de
grid-template-areasdoit avoir le même nombre de noms de zones.
Flux de placement par zones nommées
4. Zone de Danger
❌ Erreur commune : Essayer de nommer une zone sur l'élément enfant sans l'avoir définie dans le container.
Exemple : Mettre grid-area: sidebar; sur un élément alors que grid-template-areas n'est pas défini. L'élément sera alors traité comme un nom de ligne, ce qui peut mener à des comportements imprévisibles.
✅ Bonne pratique : Toujours définir le plan global dans le container avant d'assigner les zones aux enfants.
Questions clés
1. Quelle est la différence fondamentale entre grid-column: 1 / 2 et grid-column: 1 / span 1 ?
Découvrir la réponse
Visuellement, le résultat est identique : l'élément occupe la première colonne. La différence est conceptuelle. 1 / 2 définit des bornes fixes (ligne 1 à ligne 2). 1 / span 1 définit un point de départ et une largeur. Le span est plus flexible si vous changez le point de départ sans vouloir modifier la largeur de l'élément.
2. Que se passe-t-il si j'utilise grid-column: 1 / -1 ?
Découvrir la réponse
L'élément s'étendra de la première colonne jusqu'à la dernière colonne de la grille, occupant ainsi toute la largeur disponible, peu importe le nombre de colonnes définies.
3. Peut-on superposer deux éléments dans une grille ?
Découvrir la réponse
Oui. Contrairement au flux classique ou à Flexbox, CSS Grid permet à plusieurs éléments d'occuper la même zone (mêmes colonnes et rangées de début et de fin). L'ordre d'empilement est alors géré par le z-index ou l'ordre d'apparition dans le HTML.
4. Pourquoi utiliser grid-template-areas plutôt que grid-column / grid-row ?
Découvrir la réponse
Pour la lisibilité et la maintenance. grid-template-areas permet de visualiser la structure de la page directement dans le code CSS. C'est également beaucoup plus simple pour réorganiser le layout lors du passage au responsive (on change juste la "carte" des zones).
5. Est-il possible de laisser un trou vide dans une grille avec les zones nommées ?
Découvrir la réponse
Oui, en utilisant le symbole point . dans la définition de grid-template-areas. Par exemple : "header . header" créera une colonne vide au centre de la première ligne.
Mise en pratique
Exercice 1 : Reproduction guidée (Niveau Junior)
Objectif : Créer une grille simple de 3 colonnes et 3 lignes.
- Un élément "Header" doit occuper toute la première ligne.
- Un élément "Main" doit occuper la colonne 2, de la ligne 2 à 3.
- Un élément "Footer" doit occuper toute la dernière ligne.
Découvrir la solution commentée
.container {
display: grid;
/* repeat(3, 1fr) est équivalent à écrire: 1fr 1fr 1fr */
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(3, 100px);
gap: 10px;
}
.header {
/* Ligne 1, de la colonne 1 à la fin */
grid-column: 1 / -1; /* Équivalent à: grid-column: 1 / span 3 */
grid-row: 1 / 2;
}
.main {
/* Colonne 2, lignes 2 et 3 */
grid-column: 2 / 3;
grid-row: 2 / 4;
}
.footer {
/* Ligne 3, toute la largeur */
grid-column: 1 / -1; /* Équivalent à: grid-column: 1 / span 3 */
grid-row: 3 / 4;
}
Exercice 2 : Adaptation (Niveau Intermédiaire)
Objectif : Transformer le layout suivant utilisant des lignes en un layout utilisant des zones nommées.
- Header :
grid-column: 1 / 4,grid-row: 1 / 2 - Sidebar :
grid-column: 1 / 2,grid-row: 2 / 4 - Content :
grid-column: 2 / 4,grid-row: 2 / 3 - Ads :
grid-column: 2 / 4,grid-row: 3 / 4
HTML de départ :
<div class="container">
<header class="header">Header</header>
<aside class="sidebar">Sidebar</aside>
<main class="content">Contenu principal</main>
<section class="ads">Publicités</section>
</div>
Ajoutez une couleur de fond distincte à chaque zone (ex : background-color: #3498db pour le header, #2ecc71 pour la sidebar, etc.) et quelques lignes de texte pour bien visualiser la disposition.
Découvrir la solution commentée
.container {
display: grid;
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"header header header"
"sidebar content content"
"sidebar ads ads";
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.content { grid-area: content; }
.ads { grid-area: ads; }
Exercice 3 : Conception (Niveau Intermédiaire)
Objectif : Créer un "Bento Grid" (style Apple/Microsoft) en utilisant span et grid-area.
HTML de départ :
<div class="bento-grid">
<div class="item item-hero">Héros</div>
<div class="item item-a">A</div>
<div class="item item-b">B</div>
<div class="item item-wide">Large</div>
</div>
Consignes :
- Créez une grille de 4 colonnes et 2 rangées (hauteur des rangées : 200px).
.item-hero: doit occuper les 2 premières colonnes et les 2 rangées. Utilisezspanpour exprimer cette largeur (grid-column: 1 / span 2)..item-aet.item-b: occupent chacun une cellule en colonne 3 et 4 respectivement, sur la première rangée..item-wide: doit occuper les colonnes 3 et 4 sur la deuxième rangée. Utilisezspanici aussi.- Définissez des
grid-areanommées sur le container (viagrid-template-areas) et assignez chaque item à sa zone. - Ajoutez une couleur de fond distincte à chaque item.
Découvrir la solution commentée
.bento-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(2, 200px);
gap: 1rem;
/* Disposition visuelle des zones nommées */
grid-template-areas:
"hero hero item-a item-b"
"hero hero wide wide";
}
/* Assignation des zones à chaque item */
.item-hero { grid-area: hero; }
.item-a { grid-area: item-a; }
.item-b { grid-area: item-b; }
.item-wide { grid-area: wide; }
/* Couleurs pour visualiser la disposition */
.item-hero { background: #3498db; }
.item-a { background: #e74c3c; }
.item-b { background: #f1c40f; }
.item-wide { background: #2ecc71; }
/* Style commun */
.item {
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.5rem;
font-weight: bold;
border-radius: 12px;
}
Rappel span : si vous préférez ne pas utiliser grid-template-areas, vous obtenez le même résultat avec :
.item-hero { grid-column: 1 / span 2; grid-row: 1 / span 2; }
.item-a { grid-column: 3 / span 1; grid-row: 1 / span 1; }
.item-b { grid-column: 4 / span 1; grid-row: 1 / span 1; }
.item-wide { grid-column: 3 / span 2; grid-row: 2 / span 1; }