CSS Grid

Grid range des éléments sur deux dimensions à la fois — lignes ET colonnes. Là où Flexbox aligne une rangée, Grid compose une page entière.

Flexbox ou Grid : lequel choisir

Les deux répartissent de l’espace. L’un le fait sur un axe, l’autre sur deux — et c’est tout ce qui les sépare.

1D Flexbox — une dimension

  • Navigation horizontale ou verticale
  • Centrage et alignement
  • Distribution d’espace
  • Mises en page en ligne ou en colonne
  • Composants d’interface simples
Flexbox : une seule direction.

2D Grid — deux dimensions

  • Mises en page de page entière
  • Grilles de contenus
  • Positionnement précis
  • Compositions complexes en 2D
  • Adaptation avancée aux écrans
Grid : les lignes ET les colonnes.

L’anatomie d’une grille

Grid Container
Élément portant display: grid
Grid Items
Enfants directs du conteneur
Grid Lines
Lignes de séparation entre les pistes
Grid Cells
Intersection d’une ligne et d’une colonne
Grid Areas
Zones nommées couvrant plusieurs cellules
Trois colonnes sur trois lignes, avec des éléments qui débordent sur plusieurs cellules (span) et un espacement régulier.

Les propriétés du conteneur

Elles se posent sur le conteneur et gouvernent tous ses enfants d’un coup.

display: grid

Une seule déclaration transforme un élément en grille. Ses enfants directs deviennent des éléments de grille et se placent tout seuls.

css

/* Activation de CSS Grid */
.container {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    gap: 1rem;
}

/* Alternative inline */
.container-inline {
    display: inline-grid;
}

inline-grid produit la même grille, mais l’élément reste dans le flux du texte.
Six éléments, trois colonnes : les lignes se créent d’elles-mêmes.

Explorer grid-template-columns

grid-template-columns

1
2
3
4
5
6

grid-template-columns: ;

repeat(auto-fit, minmax(150px, 1fr)) est la seule de ces cinq valeurs à s’adapter seule à la largeur : aucune media query n’est nécessaire.

Explorer gap

gap

1
2
3
4
5
6

gap: ;

Deux valeurs séparées par une espace donnent d’abord l’espacement des lignes, puis celui des colonnes.

Explorer l’alignement des éléments dans leur cellule

justify-items / align-items

1
2
3
4
5
6

justify-items: ;
align-items: ;

stretch est la valeur par défaut : chaque élément occupe toute sa cellule. Les trois autres le laissent à sa taille propre et le placent dans la cellule.

Les unités propres à Grid

Les zones nommées, une mise en page qui se lit

grid-template-areas dessine la page en toutes lettres. Le code ressemble à ce qu’il produit — c’est là tout son intérêt, et c’est pourquoi il se lit plutôt qu’il ne s’explore.

Configuration du layout

css

.layout {
    display: grid;
    grid-template-columns: 200px 1fr 200px;
    grid-template-rows: 60px 1fr 40px;
    grid-template-areas:
        "header header header"
        "sidebar main aside"
        "footer footer footer";
    gap: 10px;
    height: 100vh;
}

/* Assignation des zones */
.header  { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main    { grid-area: main; }
.aside   { grid-area: aside; }
.footer  { grid-area: footer; }

Chaque zone occupe exactement la place que le dessin lui donne dans le code.

Ce que les zones nommées apportent

  • Le code se lit comme un plan de la page
  • Réorganiser la page revient à redessiner trois lignes
  • Une media query suffit à tout réagencer
  • Les noms disent l’intention, pas la position

Réagencer la page avec une media query

css

/* Desktop */
@media (min-width: 768px) {
    .layout {
        grid-template-areas:
            "header header header"
            "sidebar main aside"
            "footer footer footer";
    }
}

/* Mobile */
@media (max-width: 767px) {
    .layout {
        grid-template-columns: 1fr;
        grid-template-areas:
            "header"
            "main"
            "sidebar"
            "aside"
            "footer";
    }
}

Le balisage ne change pas : seules les zones sont redessinées.

Trois mises en page courantes

Les mêmes propriétés, appliquées à ce qu’on rencontre sur de vrais sites.

Galerie adaptative

Une seule déclaration, aucune media query : les colonnes se créent et se réduisent selon la place disponible.

css

/* Galerie auto-responsive */
.gallery {
    display: grid;
    grid-template-columns:
        repeat(auto-fit, minmax(200px, 1fr));
    gap: 1rem;
    padding: 1rem;
}

.gallery img {
    width: 100%;
    height: 200px;
    object-fit: cover;
    border-radius: 8px;
}

Élargissez ou rétrécissez le cadre : le nombre de colonnes suit.

Ce que fait auto-fit

  • S’adapte à toutes les largeurs d’écran
  • Minimum 200 px par colonne
  • Au-delà, les colonnes remplissent l’espace
  • Aucune media query nécessaire

Grille de cartes façon magazine

Un article en vedette occupe quatre cellules, un autre en occupe deux : le reste se place tout seul autour.

css

/* Layout magazine */
.magazine {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-template-rows: repeat(3, 150px);
    gap: 1rem;
}

.featured {
    grid-column: span 2;
    grid-row: span 2;
}

.highlight {
    grid-column: span 2;
}

FEATURED couvre 2 colonnes sur 2 lignes, HIGHLIGHT en couvre 2 sur une seule.

Tableau de bord complet

Six zones nommées, quatre colonnes, trois lignes : la structure entière d’une application tient en dix déclarations.

css

.dashboard {
    display: grid;
    grid-template-areas:
        "header header header header"
        "sidebar stats stats charts"
        "sidebar recent recent activity";
    grid-template-columns: 200px 1fr 1fr 300px;
    grid-template-rows: 60px 200px 1fr;
    gap: 1rem;
    height: 100vh;
}

.header   { grid-area: header; }
.sidebar  { grid-area: sidebar; }
.stats    { grid-area: stats; }
.charts   { grid-area: charts; }
.recent   { grid-area: recent; }
.activity { grid-area: activity; }

La barre latérale s’étend sur deux lignes, l’en-tête sur les quatre colonnes.

Ce que ce découpage apporte

  • Une mise en page complexe en quelques lignes
  • Des zones délimitées sans calcul de position
  • Un réagencement facile selon l’écran
  • Une maintenance simplifiée

Exercice : portfolio d’architecte

La mission

Créez un portfolio d’architecte avec une galerie asymétrique et des zones de contenu variées.

Ce qui est demandé

  • Un en-tête avec navigation
  • Une galerie asymétrique — certaines images plus grandes que d’autres
  • Une section « À propos » avec texte et photo
  • Une grille qui s’adapte : bureau, tablette, mobile
  • Utiliser grid-template-areas
  • Des images de tailles variables, avec grid-column et grid-row en span
Mise en page asymétrique : chaque bloc couvre un nombre de cellules différent.

Code de démarrage

html

<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Portfolio Architecte - CSS Grid</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Arial', sans-serif;
            background: #f8f9fa;
        }

        .portfolio {
            /* TODO: Créer un grid container avec areas */
            display: grid;
            /* TODO: Définir grid-template-columns pour 6 colonnes */
            /* TODO: Définir grid-template-rows avec hauteurs variables */
            /* TODO: Créer grid-template-areas pour desktop */
            gap: 1rem;
            padding: 1rem;
            min-height: 100vh;
        }

        .header {
            /* TODO: Assigner grid-area: header */
            background: #2c3e50;
            color: white;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 1rem 2rem;
            border-radius: 8px;
        }

        .project-featured {
            /* TODO: Assigner grid-area et spans pour projet principal */
            background: linear-gradient(135deg, #e74c3c, #c0392b);
            color: white;
            border-radius: 8px;
            padding: 2rem;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        .project {
            background: #3498db;
            color: white;
            border-radius: 8px;
            padding: 1rem;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
        }

        .project:nth-child(4) { background: #2ecc71; }
        .project:nth-child(5) { background: #f39c12; }
        .project:nth-child(6) { background: #9b59b6; }
        .project:nth-child(7) { background: #1abc9c; }

        .about {
            /* TODO: Assigner grid-area et gérer le contenu */
            background: white;
            padding: 2rem;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
        }

        .contact {
            /* TODO: Assigner grid-area avec span vertical */
            background: linear-gradient(135deg, #e67e22, #d35400);
            color: white;
            padding: 2rem;
            border-radius: 8px;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }

        /* TODO: Media Queries */
        @media (max-width: 768px) {
            .portfolio {
                /* TODO: Adapter grid pour tablet */
                grid-template-columns: 1fr 1fr;
                grid-template-areas:
                    "header header"
                    "featured featured"
                    "project1 project2"
                    "about about"
                    "contact contact";
            }
        }

        @media (max-width: 480px) {
            .portfolio {
                /* TODO: Adapter grid pour mobile */
                grid-template-columns: 1fr;
                grid-template-areas:
                    "header"
                    "featured"
                    "about"
                    "projects"
                    "contact";
            }
        }
    </style>
</head>
<body>
    <div class="portfolio">
        <header class="header">
            <h1>Architecture Studio</h1>
            <nav>
                <a href="#" style="color: white; text-decoration: none; margin: 0 1rem;">Projets</a>
                <a href="#" style="color: white; text-decoration: none; margin: 0 1rem;">À propos</a>
                <a href="#" style="color: white; text-decoration: none; margin: 0 1rem;">Contact</a>
            </nav>
        </header>

        <div class="project-featured">
            <h2>Projet Principal</h2>
            <p>Villa Moderne</p>
        </div>

        <div class="project">Résidentiel A</div>
        <div class="project">Bureau B</div>
        <div class="project">Commercial C</div>
        <div class="project">Culturel D</div>

        <section class="about">
            <h3>À Propos</h3>
            <p>Studio d'architecture spécialisé dans les projets durables et innovants.
               Plus de 15 ans d'expérience dans la conception de bâtiments respectueux
               de l'environnement.</p>
        </section>

        <div class="contact">
            <h3>Contact</h3>
            <p>hello@archi-studio.com</p>
            <p>+33 1 23 45 67 89</p>
        </div>
    </div>
</body>
</html>

Les commentaires TODO marquent ce qui reste à écrire.

CSS Grid est acquis

Vous savez composer une page sur deux dimensions, nommer ses zones et les réagencer selon l’écran. Grid et Flexbox ne se remplacent pas : ils se combinent.

La règle du partage

Grid pour la structure de la page, Flexbox pour l’intérieur des composants — une navigation, une carte. Les deux ensemble couvrent à peu près tout.

Les autres pages CSS