Les grilles CSS

Tout est dans la grille

L'approche présentée ici, les grilles CSS (CSS grids), est la plus récente de toutes

Elle est aussi très intuitive au niveau design

On commence par créer une grille virtuelle, puis on y place les éléments, ceux-ci pouvant recouvrir plusieurs cellules

header header header
aside section section
aside section section
footer footer footer

L'ordre de déclaration des éléments sémantiques n'a même plus d'importance!

Et surtout, on peut décider comment la page sera réorganisée lorsque change la taille de l'écran :

header header
footer footer
section section
section section
aside aside

Voyons un exemple...


Les colonnes

Supposons que nous voulions une mise en page basée sur une grille de 3 x 3 (9 cellules), avec une colonne centrale qui a deux fois la taille des autres

1 2 3
4 5 6
7 8 9

Dans un but de simplicité nous n'utiliserons pas d'éléments sémantiques, mais seulement des div

Il s'agit d'abord de déclarer nos 9 div et de les regrouper dans un conteneur (lui aussi un div)

C'est ce conteneur qui implémentera la grille avec display:grid

    #conteneur {
      display: grid;
      ...
    }
  
  <div id="conteneur">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
  </div>

Il faut ensuite spécifier le nombre de colonnes et pour cela il y a plusieurs façons

On peut déclarer le nombre de colonnes en indiquant du même coup la taille à l'aide des unités CSS (généralement le pourcentage) :

    #conteneur {
      display: grid
      grid-template-columns: 25% 50% 25%;
      ...
    }

On peut aussi utiliser les fractions :

    #conteneur {
      display: grid
      grid-template-columns: 1fr 2fr 1fr;
      ...
    }

Enfin, si toutes les colonnes ont la même largeur, on peut utiliser la fonction repeat :

    #conteneur {
      display: grid
      /* grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr; */
      grid-template-columns: repeat(6, 1fr);
      ...
    }

Dans l'exemple suivant, la largeur de la mise en page a été réduite à 480px pour faciliter l'affichage

Exemple
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <title>Les grilles CSS</title>
<style>
  body {
    text-align: center;
  }
  #conteneur {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    max-width: 480px;
    margin: 0 auto;
  }
  #conteneur div {
    background: yellow;
    padding: 20px;
  }
  #conteneur div:nth-child(even) {
    background: lime;
  }
</style>
</head>
<body>
  <div id="conteneur">
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <div>9</div>
  </div>
</body>
</html>

Les rangées

Par défaut, la hauteur des rangées s'ajuste au contenu (en plus de la valeur de la propriété padding)

On peut aussi fixer la hauteur des rangées

Voici l'exemple d'une grille de 6 colonnes et de 3 rangées (les deux premières d'une hauteur de 100px, la trosième de 50px) :

    #conteneur {
      display: grid
      grid-template-columns: repeat(6, 1fr);
      grid-template-rows: 100px 100px 50px;
      ...
    }

Ici les rangées auront toutes la même hauteur, peu importe leur nombre :

    #conteneur {
      display: grid
      grid-template-columns: repeat(6, 1fr);
      grid-auto-rows: 100px;
      ...
    }

On peut aussi s'assurer d'une hauteur minimale, tout en permettant l'étirement vertical si le contenu l'exige :

    #conteneur {
      display: grid
      grid-template-columns: repeat(6, 1fr);
      grid-auto-rows: minmax(100px, auto);
      ...
    }

Dans l'exemple suivant, on utilise la fonction repeat pour donner les mêmes valeurs de minimum et de maximum aux trois rangées :

    #conteneur {
      display: grid
      grid-template-columns: repeat(6, 1fr);
      grid-template-rows: repeat(3, minmax(100px, auto));
      ...
    }

Avant de voir un exemple complet, signalons qu'il est aussi possible de spécifier l'espace entre les les colonnes et entre les rangées :

    #conteneur {
      display: grid
      grid-template-columns: repeat(6, 1fr);
      grid-template-rows: repeat(3, minmax(100px, auto));
      column-gap: 20px;
      row-gap: 20px;
      ...
    }

Ces deux dernière propriétés pourraient être remplacées par une seule : grid-gap: 20px;

Et maintenant un exemple complet pour pratiquer...

Exemple
  body {
    text-align: center;
  }
  #conteneur {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-auto-rows: minmax(100px, 150px);
    /* la ligne suivante afficherait tout  */
    /* grid-auto-rows: minmax(100px auto); */
    column-gap: 20px;
    row-gap: 10px;
    max-width: 480px;
    margin: 0 auto;
  }
  #conteneur div {
    background: yellow;
    padding: 20px;
  }
  #conteneur div:nth-child(even) {
    background: lime;
  }

Lignes de colonnes et lignes de rangées

Nous avons vu qu'à l'intérieur d'un conteneur ayant la propriété display:grid, les éléments sont placés dans la grille virtuelle selon l'ordre de leur déclaration dans le fichier HTML

Mais il s'agit là du comportement par défaut

Il existe une façon beaucoup plus souple de positionner les éléments, soit en utilisant les lignes de colonnes et les lignes de rangées

Ces lignes, que l'on peut voir dans la figure suivante, débute à 1 et vont jusqu'à n+1n est le nombre de colonnes ou le nombre de rangées

grid lines
Source w3schools.com

Voyons un exemple...

Supposons une grille de 6 x 4 contenant 6 éléments (pour l'instant encore des div)

Au départ, les éléments sont positionnés chacun dans une cellule selon l'ordre de déclaration :

           
 
 
 

Maintenant, supposons que l'objectif final est de les postionner ainsi :

           
           
           
           

On remarque que la sixième élément (gris) est passé devant le cinquième (noir)

Commençons par définir le nombre de colonnes et de lignes de la grille :

Exemple
  #conteneur {
    display: grid;
    grid-template-columns: repeat(6, 1fr);             /* 6 colonnes */
    grid-template-rows: repeat(4, minmax(75px, auto)); /* 4 rangées */
    grid-gap: 10px;
    max-width: 480px;
    margin: 0 auto;
  }
  .un {
    background-color: red;
  }
  .deux {
    background-color: green;
  }
  ...
  
  <div id="conteneur">
    <div class="un"></div>
    <div class="deux"></div>
    ...
Je teste

Maintenant, commençons à positionner les éléments en spécifiant les lignes de départ et de fin :

  .un {
    background-color: red;
    grid-column-start: 1;
    grid-column-end: 3;
  }

On peut aussi utiliser une notation abrégée :

  .un {
    background-color: red;
    grid-column: 1/3;
  }
  .deux {
    background-color: green;
    grid-column: 3/7;
  }

Notons qu'il n'est pas nécessaire de spécifier ici les lignes de rangées, puisque les éléments n'occupent en hauteur qu'une seule rangée

Poursuivons en plaçant le troisième item sur trois colonnes et deux rangées :

  .trois {
    background-color: blue;
    grid-column: 1/4;
    /* grid-row-start: 2; */
    /* grid-row-end:   4; */
    grid-row: 2/4;
  }

Et plaçons le reste des éléments...

Exemple
  .quatre {
    background-color: yellow;
    grid-column: 4/7;
    grid-row: 2/4;
  }
  /* cinq positionné après six */
  .cinq {
    background-color: black;
    grid-column: 3/7;
  }
  .six {
    background-color: gray;
    grid-column: 1/3;
    grid-row: 4;
  }

Les zones

C'est cependant avec le concept de zones que les grilles CSS montrent toute leur souplesse et toute leur puissance

Supposons par exemple que nous voulions réaliser la mise en page suivante :

grid zones

Cette fois nous allons utiliser les éléments sémantiques appropriés et non plus des conteneurs généraux comme l'élément div

Sans spécifier le nombre de colonnes et de rangées, ni la position exacte des éléments, ces derniers s'empilent simplement à la verticale

Exemple
<!DOCTYPE html>
<html lang="fr">
<head>
  <meta charset="UTF-8">
  <title>Les grilles CSS</title>
<style>
  body {
    text-align: center;
  }
  #conteneur {
    display: grid;
    grid-gap: 10px;
    max-width: 480px;
    margin: 0 auto;
  }
  #conteneur > * {
    background-color: lime;
    padding: 30px;
  }
</style>
</head>
<body>
  <div id="conteneur">
    <header>header</header>
    <main>main</main>
    <section>section</section>
    <aside>aside</aside>
    <nav>nav</nav>
    <footer>footer</footer>
  </div>
</body>
</html>

Utilisons maintenant la propriété grid-area pour assigner à chaque élément une position dans la grille

Cette position est exprimée sous la forme d'une chaîne de caractères

  header {
    grid-area: header;
  }
  main {
    grid-area: main;
  }
  section {
    grid-area: section;
  }
  aside {
    grid-area: aside;
  }
  nav {
    grid-area: nav;
  }
  footer {
    grid-area: footer;
  }

Dans notre exemple, le nom de la zone dans laquelle sera positionné l'élément (la valeur de la propriété grid-area) correspond au nom de l'élément

Par exemple, nous avons choisi de nommer "header" la zone où sera postionné l'élément header

Il s'agit d'une pratique répandue, mais pas du tout obligatoire

Le code suivant serait tout aussi valable :

  header {
    grid-area: entete;
  }

Déclarons maintenant le nombre de colonnes et de rangées :

  #conteneur {
    display: grid;
    grid-template-columns: repeat(4, 1fr);   /* 4 colonnes */
    grid-auto-rows: minmax(75px, auto);      /* autant de rangées qu'il faut */
    grid-gap: 10px;
    max-width: 480px;
    margin: 0 auto;
    ...

Puis, plaçons dans la grille les zones correspondant aux éléments structurants :

Exemple
  #conteneur {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-auto-rows: minmax(75, auto);
    grid-gap: 10px;
    max-width: 480px;
    margin: 0 auto;
    grid-template-areas:
	"header  header  header  header"
	"aside   aside   main    main"
	"nav     nav     main    main"
	"section section section section"
	"footer  footer  footer  footer"; /* ne pas oublier le point-virgule */
  }

Et voilà!

Changer la position ou la superficie occupée par un élément se résume maintenant à "jouer" avec les zones du grid-template-area


Début du document