CSS et la disposition en grille ou grid layout

Le module de disposition en grille de CSS permet de positionnement facilement les éléments d’une interface en divisant l’espace de la page en zones.

Qu’est-ce que la disposition en grille en CSS ?

Historiquement, les tableaux HTML ont longtemps été utilisés pour positionner les éléments les uns par rapport aux autres. Il s’agissait de tableaux dont les bordures étaient masquées et dont les différentes cellules contenaient les éléments d’interface. L’exercice n’était pas toujours évident, il fallait souvent fusionner des cellules, imbriquer plusieurs tableaux les uns dans les autres et utiliser des images transparentes pour forcer les dimensions d’une cellule particulière.

Le module de disposition en grille de CSS, également appelé grid layout en anglais, est la version améliorée de cette époque révolue (et heureusement) de positionnement via des tableaux. La différence notable entre la disposition en grille et un tableau HTML est que la grille CSS reste virtuelle et ne nécessite pas de structure HTML.

L’interface web suivante peut être intégrée dans une grille, pour cela, il suffit de diviser l’interface en ligne et en colonnes comme vous pouvez le voir avec les traits pointillés qui représente une grille virtuelle. Vous remarquerez que certains des éléments comme les encarts publicitaires ou le contenu central occupent une seule cellule de notre grille virtuelle quand d’autres éléments en occupent plusieurs. Il est donc nécessaire d’avoir un certain degré d’abstraction lorsque l’on travaille avec une grille.

Découpage d'une interface en grille
Découpage d’une interface en grille

Le vocabulaire de base du système de grille

Afin d’aborder sereinement le fonctionnement du positionnement en grille de CSS, il est important de bien maîtriser le vocabulaire de base.

Le conteneur et les éléments de grille

Une grille se basera obligatoirement sur un conteneur de grille, ou en anglais, grid container. C’est cet élément HTML qui est déclaré comme une grille en CSS.

Le conteneur de grille contient des éléments de grille, ou grid items en anglais qui peuvent donc être positionnés à volonté à l’intérieur du conteneur en fonction des zones définies dans la grille.

Ainsi dans la grille suivante, le conteneur est l’élément <div> utilisant la classe container et ses enfants (les éléments <div> à l’intérieur) sont tous les trois des grid items.

Illustration conteneur de grille
<div class="container">
    <div>A</div>
    <div>B</div>
    <div>C</div>
</div>

Les pistes

Les pistes de grille, ou grid tracks, correspondent aux rangés et aux colonnes générées virtuellement lors de la création d’une grille.

Dans l’illustration suivante, la grille se compose de trois pistes horizontales (rangés) dont la seconde est identifiée en bleu et de six pistes verticales (colonnes) dont la cinquième est identifiée en rouge.

Pistes de grille

Les lignes

Les lignes, qui ne doivent surtout pas être confondues avec les pistes, correspondent aux “traits” virtuels tracés pour dessiner une grille. Il y a donc des lignes de rangé (row line) et des lignes de colonne (column line).

Ces lignes de rangé et de colonnes sont numérotées afin que l’on puisse y faire référence par la suite lors du positionnement des éléments de la grille.

Ainsi dans l’illustration suivante, la grille est construite à partir de quatre lignes de rangé dont la troisième est identifiée en bleu et de sept lignes de colonnes dont la cinquième est identifiée en rouge.

Lignes de grille

Remarquez que, contrairement aux habitudes en informatique, la numérotation des lignes commence à 1 et pas à 0.

Les zones et cellules

Les lignes d’une grille permettent de délimiter des cellules de grille ou grid cells.

Un ensemble de cellules est appelé une zone de grille ou grid area.

Dans l’illustration suivante, une cellule a été identifiée en bleu et une zone de grille composée de six cellules a été identifiée en rouge.

cellules et zones

Comment construire une grille ?

Déclaration d’une grille

Pour construire une grille, il est nécessaire d’avoir un élément HTML qui va servir de conteneur. Techniquement, vous pouvez utiliser n’importe quel élément HTML, mais il est recommandé d’utiliser un élément de type <div> ou bien un élément sémantique cohérent du genre <article> ou <section>.

Pour la mise en place de la grille, sans contenu, il est donc uniquement nécessaire d’avoir le code ci-dessous dans une page HTML. Le nom de classe étant évidemment à votre convenance.

<div class="grid-container">
</div>

Une fois le conteneur HTML en place, il s’agit de le déclarer comme une grille via CSS. Pour cela, vous devez utiliser la propriété CSS display à laquelle vous pouvez associer la valeur grid pour une grille classique.

.grid-container {
   display: grid;
}

Vous pouvez également utiliser la valeur inline-grid si vous souhaitez créer une grille qui se comporte comme un élément de type inline. Pour en savoir plus sur les éléments inline, veuillez consulter l’article suivant Les niveaux ou types d’éléments en CSS.

Dimensionnement des pistes

Une fois la grille déclarée, il faut indiquer le nombre de colonnes et de rangés que l’on souhaite. Pour cela, il faut utiliser les propriétés grid-template-columns et grid-template-rows.

La propriété grid-template-columns permet donc de définir le nombre de colonnes. Il s’agit donc d’indiquer la largeur des différentes colonnes souhaitées. Le nombre de valeurs saisies va ainsi définir le nombre de colonnes.

Le principe est le même pour la propriété grid-template-rows à laquelle il faut associer les hauteurs des différentes lignes.

Les dimensions saisies peuvent utiliser les valeurs suivantes :

  • px : une dimension fixe.
  • % : un pourcentage positif relatif à la taille du conteneur de la grille.
  • fr : correspond à une fraction de l’espace libre du conteneur de la grille.
  • auto : les dimensions vont s’adapter en fonction du contenu des pistes.

D’autres valeurs sont possibles, pour en savoir plus vous pouvez consulter l’article suivant https://developer.mozilla.org/fr/docs/Web/CSS/grid-template-columns.

Voici donc un exemple de grille représentée graphiquement ainsi que le code correspondant. La grille se compose de trois colonnes et deux rangés, il y a donc trois valeurs pour grid-template-columns et deux valeurs pour grid-template-rows.

Exemple de grille simple
.grid-container {
   display: grid;
   grid-template-columns: 250px auto 250px;
   grid-template-rows: 100px auto;
}

En savoir plus sur les dimensions

L’unité fr

Le modèle de grille nous offre une nouvelle unité flexible fr. Il s’agit d’une unité correspondant à des fractions de l’espace libre du conteneur. Les dimensions de l’espace libre sont calculées après avoir enlevé la somme des dimensions des items non-flexibles à la taille du conteneur.

Prenons plusieurs exemples pour illustrer le fonctionnement de cette unité de mesure flexible en nous concentrant uniquement sur les largeurs des colonnes, le principe étant identique pour les hauteurs des rangés.

Exemple

Cette grille a une dimension de 1000px de large. Il n’y a aucune unité non-flexible. La somme des trois colonnes vaut 4fr. 1fr correspond donc à 1000 / 4 = 250px. Nous avons donc une colonne de 250px, une colonne de 500px et une dernière colonne de 250px.

Exemple unité fr n°1
Représentation grille n°1
Exemple

Cette grille a une dimension de 1000px de large. La première colonne utilise une unité non-flexible. L’espace restant est de 1000 – 300 = 700px. La somme des unités flexibles est de 2. 1fr correspond donc à 700 / 2 = 350px. Nous avons ainsi une colonne de 300px et deux colonnes de 350px.

Exemple unité fr n°2

Répétition des valeurs

La fonction repeat() permet de répéter une valeur plusieurs fois. Elle fonctionne sur le principe repeat(nb_repetition, valeur).

Ainsi les deux propositions suivantes sont équivalentes :

grid-template-columns: 1fr 1fr 1fr;
grid-template-columns: repeat(3, 1fr);

La valeur auto-fill utilisable pour le nombre de répétitions demande de répéter la valeur tant qu’il reste assez de place dans la conteneur. Elle n’est donc pas compatible avec l’unité fr.

grid-template-columns: repeat(auto-fill, 200px);

Démonstration : https://codepen.io/crego/full/KKPRXPE

Intervalle de dimensions

Il est possible de définir un intervalle de taille entre deux valeurs avec la fonction minmax(min, max). La colonne (ou la rangée) est alors dimensionnée dans l’intervalle des deux dimensions fournies min et max.

Il est ainsi possible, par exemple, de demander à une colonne de faire 50% de large mais d’avoir une largeur minimale de 200px.

grid-template-columns: minmax(200px,50%) 200px 200px;

Démonstration : https://codepen.io/crego/full/BaKPGmN
Notez que minmax() fonctionne aussi avec des mots clés min-content, max-content.

Positionnement automatique des éléments sur la grille

Position par défaut des éléments

Par défaut, si les éléments de la grille ne sont pas explicitement positionnés, ceux-ci vont se positionner automatiquement. Ils occuperont alors chacun une cellule de la grille dans l’ordre de leur place dans le code HTML. Si le nombre de cellules de la grille est supérieur au nombre d’éléments, il y aura donc des cellules vides.

Dans l’exemple ci-dessous, les éléments ont été colorés pour une meilleure compréhension de leur position dans la grille.

Code CSS :

.grid-container {
   display: grid;
   grid-template-columns: 1fr 1fr 1fr;
   grid-template-rows: 100px 300px;
}

Code HTML :

<div class="grid-container">
   <div>A</div>
   <div>B</div>
   <div>C</div>
   <div>D</div>
   <div>E</div>
</div>
Exemple positionnement par défaut

Remplissage vertical de la grille

Comme nous venons de le voir, par défaut les cellules de la grille se remplissent par rangé. Il est possible de changer le sens de remplissage en utilisant la propriété grid-auto-flow et en lui attribuant la valeur column à la place de la valeur par défaut row. Ainsi les éléments de la grille se positionneront les uns à la suite des autres par colonne.

Code CSS :

.grid-container {
   display: grid;
   grid-auto-flow: column;
   grid-template-columns: 1fr 1fr 1fr;
   grid-template-rows: 100px 300px;
}

Code HTML :

<div class="grid-container">
   <div>A</div>
   <div>B</div>
   <div>C</div>
   <div>D</div>
   <div>E</div>
</div>
Remplissage vertical

Démonstration : https://codepen.io/crego/full/QWWozmb

Remplissage des “trous” ou densification des éléments

Dans les deux exemples précédents, tous les éléments occupent une cellule de la grille. Mais ce ne sera pas toujours le cas, il est possible de faire en sorte qu’un élément en particulier occupe plusieurs cellules (une plage de cellules) verticales ou horizontales. De fait, le positionnement automatique peut alors créer des trous dans la grille.

Dans l’illustration ci-dessous, nous voyons bien que l’élément C qui occupe deux cellules (nous n’avons pas encore vu comment, mais cela va venir) ne rentre pas dans la cellule à côté de B. L’élément C passe donc sur la ligne suivante. Une cellule de la grille reste donc vide.

Trou dans la grille

Il est possible de changer ce comportement par défaut en ajoutant le mot clé dense avec la propriété grid-auto-flow.

.grid-container {
   display: grid;
   grid-auto-flow: row dense;
   grid-template-columns: 1fr 1fr 1fr;
   grid-template-rows: 100px 300px;
}
Densification

Démonstration : https://codepen.io/crego/full/KKzBrBm

Positionner les éléments par rapport aux lignes de la grille

Les propriétés de positionnement d’élément

Nous venons de voir que les éléments se positionnent automatiquement dans la grille. Mais ce comportement ne fonctionne que si les éléments ne sont pas explicitement positionnés, ce qu’il est possible de faire en se basant sur les lignes de la grille.

Les propriétés permettant de positionner un élément par rapport aux lignes sont :

  • grid-column-start : indique à partir de quelle ligne verticale l’élément s’affiche ;
  • grid-column-end : indique jusqu’à quelle ligne verticale l’élément s’affiche ;
  • grid-row-start : indique à partir de quelle ligne horizontale l’élément s’affiche ;
  • grid-row-end : indique jusqu’à quelle ligne horizontale l’élément s’affiche.

Il existe une version raccourcie qui regroupe la ligne de fin et la ligne de début. Il faut alors séparer les deux valeurs par le signe / :

  • grid-column : pour les lignes verticales (exemple : grid-column: 1 / 3) ;
  • grid-row : pour les lignes horizontales.

Attention, toutes ces propriétés s’appliquent sur les éléments et non sur la grille elle-même.

Voici quelques exemples pour illustrer le fonctionnement de ces propriétés. Nous utiliserons toujours le même code HTML et CSS pour créer la grille. La grille contient un seul élément positionnable qui utilise la classe item.

Code HTML de la grille d’exemple :

<div class="grid-container">
   <div class="item">A</div>
</div>

Code CSS de la grille d’exemple :

.grid-container {
   display: grid;
   grid-template-columns: 1fr 1fr 1fr;
   grid-template-rows: 100px 100px 100px;
}

Grille d'exemple
Exemple

Dans ce premier exemple, item est uniquement positionné pour la colonne de départ. Il doit commencer à partir de la seconde ligne verticale. La rangée de départ n’est pas spécifiée, item utilise donc la rangé qu’il aurait utilisé naturellement. L’élément occupe une seule cellule à partir de la position indiquée.

.item {
   grid-column-start: 2;
}
Exemple 1 de positionnement par rapport à une ligne
Exemple

Dans ce deuxième exemple, item est positionné pour la colonne de départ et la rangé de départ. Il doit commencer à partir de la troisième ligne verticale et à partir de la seconde ligne horizontale. L’élément occupe une seule cellule à partir de la position indiquée.

.item {
   grid-column-start: 3;
   grid-row-start: 2;
}
Exemple 2 de positionnement par rapport à une ligne
Exemple

Dans ce troisième exemple, item est positionné pour la colonne de départ, la colonne de fin, la rangé de départ et la rangé de fin. Il doit commencer à partir de la deuxième ligne verticale pour aller jusqu’à la quatrième et à partir de la seconde ligne horizontale pour aller jusqu’à la quatrième. L’élément occupe ainsi une plage de quatre cellules.

.item {
   grid-column-start: 2;
   grid-column-end: 4;
   grid-row-start: 2;
   grid-row-end: 4;
}
Exemple 3 de positionnement par rapport à une ligne
Exemple

Dans ce dernier exemple, item est positionné par rapport à la colonne de fin et la rangé de fin. Il doit donc s’arrêter à la troisième ligne verticale et à la quatrième ligne horizontale. Sans indication contraire, l’élément occupe ainsi une seule cellule.

.item {
   grid-column-end: 3;
   grid-row-end: 4;
}
Exemple 4 de positionnement par rapport à une ligne

Nommage des lignes

Lors de la construction de la grille, il est possible de donner des noms aux différentes lignes. Une fois les lignes nommées, il est possible de positionner les éléments en utilisant les noms des lignes à la place de leur numéro.

Pour nommer une ligne, il suffit de mettre son nom entre [] à l’emplacement correspondant lors du dimensionnement des pistes.

.grid-container {
   display: grid;
   grid-template-columns: [debut] 1fr [second] 1fr [troisieme] 1fr [derniere];
   grid-template-rows: [truc] 100px [chose] 100px [bidule] 100px [machin];
}
Exemple de lignes nommées

Voici un exemple de positionnement d’un élément en utilisant les noms des lignes plutôt que leur numéro.

.item {
   grid-column-start: debut;
   grid-column-end: troisieme;
   grid-row-start: chose;
   grid-row-end: bidule;
}
Utilisation des lignes nommées

Étendre une cellule avec le mot clé span

Pour positionner un élément sur plusieurs cellules, nous avons vu qu’il était possible de donner les lignes de départ et de fin. Une seconde solution consiste à donner explicitement les lignes de départ et à utiliser le mot span pour les lignes de fin (ou l’inverse) pour indiquer sur combien de cellules l’élément doit s’étendre.

Exemple

Dans cet exemple, item est positionné par rapport à la ligne verticale 1 et la ligne horizontale 2. La ligne verticale de fin n’est pas donnée explicitement, il est demandé à l’élément de s’étirer sur deux cellules.

.item {
   grid-column-start: 1 ;
   grid-column-end: span 2;
   grid-row-start: 2;
}
Exemple 1 avec span
Exemple

Exemple 2 : Dans ce dernier exemple, item est positionné par rapport à la colonne de fin et la rangé de fin. Il doit donc s’arrêter à la troisième ligne verticale et à la quatrième ligne horizontale. Sans indication contraire, l’élément occupe ainsi une seule cellule.

.item {
   grid-column-start: 2 ;
   grid-column-end: span 2;
   grid-row-start: 1;
   grid-row-start: span 3;
}
Exemple 2 avec span

Positionner les éléments en utilisant des zones d’affichage

Le système de positionnement en grille permet de définir des zones de grille dans lesquelles, les éléments peuvent être positionnés simplement. Cette méthode de positionnement est probablement la plus simple à employer pour positionner les éléments d’une interface. Une fois que la grille est définie, il suffit de créer des zones d’affichage en utilisant la fonction grid-template-areas.

Déclaration des zones

La première chose à faire est de déclarer les différentes zones de l’interface avec la propriété grid-template-areas.

Pour illustrer ce principe, le plus simple va être de prendre un exemple concret. Prenons donc la grille suivante :

.grid-container {
   display: grid;
   grid-template-columns: 140px auto;
   grid-template-rows: 80px auto 50px;
}
Exemple de grille vide

Nous allons maintenant créer des zones d’affichage. Cela consiste tout simplement à nommer des plages de cellules. Dans la valeur de grid-template-areas, chaque ligne représente une rangé de la grille et chaque nom saisi correspond à une cellule.

D’après notre exemple ci-dessous, la première piste horizontale contient deux fois le nom entete, cela signifie donc que nous avons créé une zone nommée entete qui est composée de deux cellules. La seconde piste horizontale se compose quant à elle de deux zones menu et contenu. Et pour finir, la dernière piste horizontale de la grille contient une seule zone de deux cellules qui s’appelle pied.

.grid-container {
   display: grid;
   grid-template-columns: 140px auto;
   grid-template-rows: 80px auto 50px;
   grid-template-areas: "entete entete"
                        "menu  contenu"
                        "pied pied";
}
Zone définies dans la grille

Association des éléments et des zones

Une fois les zones déclarées, il suffit de déclarer pour chaque élément de l’interface dans quelle zone il doit s’afficher. Il nous faut donc une structure HTML contenant les différents éléments à afficher.

Soit le code HTML suivant :

<div class="grid-container">
  <div class="header">En-tête</div>
  <div class="nav">Menu</div>
  <div class="content">Contenu de la page</div>
  <div class="footer">Pied de page</div>
</div>

Il suffit maintenant de positionner chaque élément en utilisant sa classe avec la propriété grid-area.

.grid-container {
   display: grid;
   grid-template-columns: 140px auto;
   grid-template-rows: 80px auto 50px;
   grid-template-areas: "entete entete"
                        "menu  contenu"
                        "pied pied";
}
.header {
   grid-area: entete;
}
.nav{
   grid-area: menu;
}
.content{
   grid-area: contenu;
}
.footer{
   grid-area: pied;
}

Articles connexes

Sauf mention contraire*, l'article CSS et la disposition en grille ou grid layout et son contenu par Julien Crego sont mis à disposition selon les termes de la licence Creative Commons

Licence Creative Commons

Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International

Cette licence vous permet de remixer, arranger, et adapter cette œuvre à des fins non commerciales tant que vous créditez la source en citant le nom des auteurs et que les nouvelles œuvres sont diffusées selon les mêmes conditions.

* Cette notice est intégrée automatiquement à la fin de chaque article de ce site.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.