CSS - Grid

Nous avons vu le module Flexbox : il est désormais temps de passer au niveau supérieur avec Grid.

Toute la documentation peut être trouvée ici : https://developer.mozilla.org/fr/docs/Learn/CSS/CSS_layout/Grids. Un guide complet de Grid peut également être lu ici : https://css-tricks.com/snippets/css/complete-guide-grid/

Pourquoi Grid ?

Grid répond à un souci auquel Flexbox ne répond pas : la mise en page selon des lignes et colonnes, ou dit autrement selon un quadrillage de la page.

Grid partage avec flexbox des concepts similaires : conteneur, éléments enfants, gestion de l’espace. Ici, notre conteneur ne sera pas un conteneur flex mais un conteneur grid.

Le conteneur

Un conteneur grid se déclare avec la règle CSS display: grid. Allez sur ce CodePen et essayez de déclarer le conteneur comme étant un conteneur grid : https://codepen.io/nugetchar/pen/vYWEoQG. Que remarquez-vous ?

Spécifier les colonnes

Comme dans une grille, on peut spécifier des colonnes. Cela se fera avec la propriété grid-template-columns.

Sa documentation est disponible ici : https://developer.mozilla.org/fr/docs/Web/CSS/grid-template-columns

Cette propriété permet de spécifier le nombre de colonnes de la grille et, pour chaque colonne, sa taille. Voici un exemple : https://codepen.io/nugetchar/pen/abVzexe.

Dans cet exemple, j’ai le code CSS suivant :

.container {
  display: grid;
  width: 100%;
  height: calc(100vh - 16px);
  background-color: blue;
  grid-template-columns: 1fr 100px 50%;
}

Ici, je spécifie trois colonnes : une de 1fr (nous y reviendrons juste après), la deuxième de 100px de largeur et la troisième qui prendra quant à elle 50% de la largeur. En spécifiant ces colonnes, mes trois blocs se retrouvent sur une seule et même ligne : chaque d’entre eux va se retrouver allouer une place.

Que signifie 1fr ? L’unité de mesure fr est énormément utilisée lorsque l’on utilise le module Grid. Elle signifie fraction et indique au navigateur que l’élément concerné prendra une certaine fraction d’espace.

Dans notre exemple, voici comment cela fonctionne :

  • la première colonne va prendre 1fr, soit 100% de l’espace restant ;
  • la deuxième colonne va prendre 100px de l’espace restant ;
  • la troisième colonne va prendre 50% en largeur de la largeur totale de son parent.

Ainsi, la première colonne n’a pas de taille “fixe” : elle s’adapte selon l’espace qu’elle peut prendre ou non.

Exercice Dans le CodePen donné en exemple, essayez de modifier les tailles en mettant :

  • 2fr pour la première colonne ;
  • 1fr pour la deuxième colonne ;
  • 1fr pour la troisième colonne.

Vous vous apercevrez que la deuxième colonne et la troisième colonne prennent la même largeur, tandis que la première colonne fais le double de la deuxième ou la troisième colonne.

Egalement, essayez de rajouter ou d’enlever des colonnes pour voir comment la grille se comporte.

Spécifier les lignes

Nous avons vu comment spécifier les colonnes, voici comment spécifier les lignes.

Pour spécifier les lignes, il faut utiliser la propriété CSS grid-template-rows. Cette propriété fonctionne de la même manière que grid-template-columns.

Sa documentation est disponible ici : https://developer.mozilla.org/fr/docs/Web/CSS/grid-template-rows.

Dans le CodePen suivant, j’ai remplacé grid-template-columns par grid-template-rows : https://codepen.io/nugetchar/pen/VwrLZRr. Vous pouvez remarquer plusieurs choses :

  • contrairement à grid-template-columns qui pouvait permettre de faire passer des éléments à la ligne, il n’y a pas de colonne supplémentaire de créée ;
  • certains éléments sont plus rapprochés que d’autres.

Concernant le dernier point, cela est dû au fait que les éléments enfants ont une hauteur fixe de 100px. Dans le CSS, changez ce 100px pour 100% pour voir la véritable hauteur des lignes.

Répéter des lignes et des colonnes

Nous venons de voir comment spécifier les colonnes et les lignes d’une grille en CSS. Néanmoins, lorsque nous les avons déclarées, nous avons, à chaque fois, spécifié la valeur. Mais que se passe-t-il si nous devons spécifier, par exemple, une dizaine de colonnes ? Ou ne serait-ce que cinq colonnes, comme pour une galerie photos ?

Prenons le CodePen suivant : https://codepen.io/nugetchar/pen/wvPavxB.

Nous avons ici cinq colonnes, spécifiées avec la règle CSS grid-template-columns: 1fr 1fr 1fr 1fr 100px;. Comme les quatre premières font la même taille, il pourrait être intéressant d’avoir une notation plus concise pour les déclarer.

C’est là qu’intervient l’instruction repeat. Sa documentation est disponible ici : https://developer.mozilla.org/fr/docs/Web/CSS/repeat().

L’instruction repeat permet de spécifier un nombre de colonnes à répéter, ainsi que leurs dimensions.

Dans notre CodePen, essayez de remplacer grid-template-columns: 1fr 1fr 1fr 1fr 100px; par grid-template-columns: repeat(4, 1fr) 100px;.

Vous ne devriez pas observer de changement notable : c’est parce que votre grille a été construite de la même manière, mais avec une notation plus concise.

On peut ainsi répéter des ensembles de colonnes comme ceci. Par exemple, remplacez votre grid-template-columns par grid-template-columns: repeat(2, 1fr 50px) 100px.

Ici, on spécifie que l’on veut deux fois une colonne de largeur 1fr et une colonne de largeurs 50px, puis une seule colonne de largeur 100px.

Ainsi, repeat permet d’avoir une écriture plus concise pour la définition de ses lignes et colonnes.

Exercice - votre première grille

Il va être temps de vous entraîner à faire votre première grille ! Pour cela, vous pouvez soit créer un CodePen, soit coder directement depuis votre éditeur de texte. Si vous le faites dans votre éditeur de texte, n’oubliez pas de rajouter la structure de base (balises html, head, et body).

À partir du code suivant, créez une grille de trois colonnes sur cinq lignes. Les dimensions des colonnes sont 1fr, 2fr, 1fr. Les dimensions des lignes sont de 100px pour les trois premières et 1fr pour tout le reste.

Code de base :

<div  class="grid">
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
	<div></div>
</div>
.grid {
	background-color: #FFE162;
	min-height: calc(100vh - 16px); 
}

.grid > div {
	background-color: #FF6464;
	border: 1px solid black;
}

Les zones - grid-template-areas

Pour encore plus de lisibilité, on peut utiliser la propriété grid-template-areas ! Cette propriété CSS permet de donner des noms aux zones de votre grille.

Par exemple, prenons la grille présente sur ce CodePen : https://codepen.io/nugetchar/pen/OJOVyGP.

Il s’agit d’un code qui peut paraître un peu trop fourni de prime abord, alors regardons-le partie par partie.

Le HTML

Partons du plus global au plus précis ! Tout en haut, le plus global, nous avons une div avec la classe grid. Il s’agira simplement de la grille qui contiendra nos éléments.

Dans cette div, nous avons trois autres div qui seront les différentes parties que nous voyons visuellement : le CV, la photo et les infos.

Dans la div de classe resume, nous retrouvons finalement toute une arborescence que nous avons déjà vu lorsque vous avez fait votre devoir sur le HTML Sémantique : un main, des sections, des titres, des paragraphes et des listes.

Dans la div de classe photo, il y a… rien ! Le fond est spécifié directement avec la propriété background-image en CSS !

Et dans la div de classe infos, il y a simplement le titre principal de notre page !

Le CSS

Ce qui va vraiment nous intéresser dans le CSS, ce sera le style spécifié à la grille et aux éléments directs de la grille.

Ainsi, pour le sélecteur .grid, on retrouve notre display: grid, la définition de nos colonnes et lignes, et le fameux grid-template-areas dont je vous parle depuis tout à l’heure ! Si l’on regarde les colonnes et les lignes, on s’aperçoit que notre grille contient deux colonnes et deux lignes. Dans notre grid-template-areas, on n’a alors plus qu’à déclarer le resume sur les deux lignes et la première colonne, la photo sur la deuxième colonne et première ligne, et les infos sur la deuxième colonne et deuxième ligne.

Mais cela ne suffit pas pour placer nos éléments ! Pour correctement les placer, il faut les cibler avec CSS et leur spécifier les zones où ils doivent se trouver, avec la propriété CSS grid-area (https://developer.mozilla.org/fr/docs/Web/CSS/grid-area) ! Par exemple, pour l’élément de classe resume, j’ai spécifié grid-area: resume : ainsi, CSS Grid va directement placer l’élément de classe resume sur la bonne zone !

La propriété raccourci grid-template

Enfin, et nous en aurons fini les templates colonnes et lignes : il existe une propriété raccourcie, grid-template (https://developer.mozilla.org/fr/docs/Web/CSS/grid-template), qui permet de spécifier d’un seul coup :

  • le nombre et taille des colonnes ;
  • le nombre et taille des lignes ;
  • les différentes zones.

Par exemple, si on reprend le CodePen précédent, on peut remplacer ces lignes de codes

.grid {
  grid-template-columns: 3fr 1fr;
  grid-template-rows: 1fr 1fr;
  grid-template-areas: 
    "resume photo"
    "resume infos";
}

par celles-ci

.grid {
    grid-template: "resume photo" 1fr
                   "resume infos" 1fr / 3fr 1fr;
}

La syntaxe devient :

grid-template: "zone zone zone..." <taille ligne>
							 "zone zone zone..." <taille ligne>
							 ...
							 "zone zone zone..." <taille ligne> / <taille col1> ... <taille coln>	

Les espaces entre les colonnes et les lignes

Comme pour Flexbox, il est possible, avec Grid, de spécifier l’écart entre colonnes et lignes avec column-gap (https://developer.mozilla.org/fr/docs/Web/CSS/column-gap) et row-gap (https://developer.mozilla.org/fr/docs/Web/CSS/row-gap).

Gestion de l’espace

Comme pour Flexbox, vous allez pouvoir retrouver les propriétés suivantes :

  • align-items : alignement vertical des éléments dans leurs zones individuelles ;
  • justify-items (non-disponible sur Flexbox) : alignement horizontal des éléments dans leurs zones individuelles ;
  • justify-content : alignement horizontal de l’ensemble des éléments dans la zone du container ;
  • align-content : alignement vertical de l’ensemble des éléments dans la zone du container ;
  • place-content: propriété raccourcie pour align-content et justify-content ;
  • place-items : propriété raccourcie pour align-items et justify-items ;

Les éléments enfants

Il est maintenant temps de voir les éléments enfants. Plutôt que de passer en revue toutes les propriétés possibles, rendez-vous sur https://cssgridgarden.com/#fr, qui propose plusieurs exercices que nous allons faire ensemble !