CSS Grid Layout
Je vais aujourd’hui vous parler d’une nouvelle méthode de disposition CSS que j’ai eu l’occasion d’utiliser dans un récent projet : CSS Grid Layout !
Qu’est-ce que CSS Grid Layout ?
Cette propriété CSS a été dévoilée officiellement en mars 2017 et son support dans la majorité des navigateurs fut relativement rapide (environ 70% en quelques mois, ce qui est assez important pour être souligné !). Je vous invite à consulter le site CanIUse pour le vérifier.
Grid Layout est le pendant de Flexbox pour une disposition bi-dimensionnelle, Flexbox se contentant des layouts “simples” et uni-dimensionnels. Il faut considérer le Grid Layout comme un tableau mais sans le balisage HTML inhérent à ce type de construction (et c’est bien CA le GROS avantage !). Adieu les <table>, <tbody>, <tr>, <td>, <th>
… Cela permet aussi de grandement simplifier l’aspect responsif de ce type de disposition et d’autoriser des mises en page beaucoup plus complexes (chevauchement par exemple).
Terminologie
Cette disposition possède sa propre terminologie qu’il est nécessaire de connaitre et de bien comprendre pour l’utiliser correctement :
- Grille (container grid) : c’est la déclaration principale à affecter à la propriété CSS display pour utiliser ce mode de disposition.
- Enfant (item grid) : c’est un descendant direct du container-grid (dans le DOM).
- Ligne (line) : représente une bordure du tableau.
- Piste (track) :
- Les pistes horizontales représentent les rangées (row)
- Les pistes verticales représentent les colonnes (column)
- Une piste est donc l’espace compris entre 2 lignes
- Cellule (cell) : représente un espace dans la grille entre 4 lignes.
- Zone (area) : Même chose que ci-dessus mais avec un regroupement de plusieurs cellules.
- Gouttière (gutter) : espacement à l’intérieur de la grille (grid-gap).
- Unités de mesure :
- Les unités “standards” de CSS peuvent évidemment être utilisées : px, %, em…
- Grid Layout apporte une unité spécifique : fr (fraction). C’est une unité relative reposant sur une fraction de l’espace disponible.
- minmax(m, n) : permet de configurer une taille comprise entre 2 bornes.
- Il est parfaitement possible de mélanger les différents types d’unités.
Fonctionnement
Le fonctionnement est très simple et peut être mis en place très rapidement :
- Créer un container avec la propriété display: grid. Attention, une fois configurée sur un élément du DOM :
- La grille va s’appliquer à tous ses enfants directs
- Les propriétés CSS “float” n’auront plus d’effet
- Contrairement à Flex, tant que le colonnage n’est pas défini, rien ne se passe !
- Configurer des colonnes et des lignes sur ce container avec les propriétés grid-template-columns et grid-template-rows
- Grille implicite : si vous n’avez pas créé suffisamment de colonnes ou de lignes pour vos éléments, Grid Layout va en ajouter pour vous. Il est possible de configurer la taille des éléments générés via les propriétés grid-auto-rows et grid-auto-columns.
- Grille explicite : elle est composée des pistes définies manuellement par les propriétés grid-template-columns/rows .
- Répétition : dans le cas où votre grille présente une disposition avec des motifs similaires, il est possible de simplifier la syntaxe avec le mot-clé repeat :
grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr;
grid-template-rows: 100px auto 20% 100px auto 20px;
grid-template-columns: repeat(3, 1fr 2fr);
grid-template-rows: repeat(2, 100px auto 20%);
- Positionner des éléments enfants à l’intérieur du container
- Positionnement automatique : par défaut, chaque élément va occuper une cellule de la grille (par défaut, le remplissage se fait en ligne).
- Pour positionner les éléments en colonne, on peut utiliser la propriété grid-auto-flow: column;
- Cette propriété permet aussi de demander à l’algorithme via la valeur dense (qui est cumulable avec column) de remplir les trous dans la grille. Dans ce cas, il est possible que l’ordre du DOM ne soit pas respecté.
- On peut aussi modifier l’ordre par défaut (qui est l’ordre du DOM) via la propriété order
- Attention aux éléments anonymes (texte sans balise par exemple) qui seront forcément positionnés en mode automatique.
- Si ça vous intéresse, l’algorithme de placement automatique est très bien décrit dans la spécification.
- Positionnement manuel : il existe plusieurs façon de positionner les éléments manuellement dans la grille
- En définissant les colonnes et lignes de début et de fin :
.box1 { grid-column-start: 1; grid-column-end: 2; grid-row-start: 1; grid-row-end: 4; }
- La même chose avec la syntaxe raccourcie :
.box1 { grid-column: 1 / 2; grid-row: 1 / 4; }
- Une syntaxe encore plus courte :) :
.box1 { grid-area: 1 / 1 / 4 / 2; }
- Et enfin avec le mot-clé “span” :
.box1 { grid-column: 1; grid-row: 1 / span 3; }
- En définissant les colonnes et lignes de début et de fin :
- Positionnement automatique : par défaut, chaque élément va occuper une cellule de la grille (par défaut, le remplissage se fait en ligne).
Voici un exemple simple qui met en évidence plusieurs possibilités de la disposition Grid :
Les zones
Elles permettent de disposer les éléments directement dans le container, sans utiliser les numéros de lignes ou de colonnes. Il n’est donc plus nécessaire de gérer individuellement les éléments. On peut indiquer que l’on souhaite laisser une cellule vide via le caractère “.”.
La propriété grid-template-areas doit obligatoirement décrire une grille complète. Dans le cas contraire, elle est considérée comme invalide et est ignorée. En clair, il faut le même nombre de cellules pour chaque ligne et chaque zone doit-être rectangulaire (la disposition en “L” est prévue dans la spécification mais n’est pas encore disponible).
Il est aussi possible de nommer les lignes entre crochets avant de définir la taille. C’est pratique, par exemple, pour venir ajouter un masque en surimpression de la grille sur une zone donnée (en utilisant les lignes implicites *-start et *-end).
Enfin, pour terminer sur le sujet, il est très pratique de combiner l’utilisation de Grid Layout avec les Media Queries pour réorganiser complétement la mise en page en fonction de la taille de l’écran (en redéfinissant grid-template-areas ).
La compatibilité avec IE
Dans mon projet, ma plus grande difficulté a été de faire fonctionner correctement mon site web avec IE :) IE10 et IE11 (ainsi que les anciennes versions de Edge) utilisent une implémentation du Grid Layout basée sur la spécification de 2011 ! Depuis le temps, il y a évidemment eu pas mal de changements et d’évolutions.
Voici quelques points sur lesquels il faut porter une attention particulière :
- Pas de positionnement automatique ! Il faut donc préciser pour chaque enfant sa position.
- Les gouttières (grid-column-gap/grid-row-gap) ne sont pas supportées. J’ai dû passer par des colonnes et des lignes “fictives” pour simuler les gouttières :) C’est probablement ce qui m’a le plus gêné…
- Les zones n’existent pas (elles sont apparues plus tard dans les spécifications)
- La notation repeat() n’existe pas
- La propriété display prend la valeur -ms-grid à la place de grid
- grid-template-columns est remplacé par -ms-grid-columns (même chose pour les lignes)
- grid-column est remplacé par -ms-grid-column (même chose pour les lignes)
- La syntaxe raccourcie
grid-column: 1 / span 2
n’est pas supportée. Il faut utiliser la propriété-ms-grid-column-span
(même chose pour les lignes)
Pour être complet sur ce sujet, je vous donne 3 liens très intéressants :
- Le blog de Rachel Andrew
- Un article qui explique comment bypasser certaines contraintes IE via SASS
- THE Guide sur le CSS Grid Layout
Pour conclure, cette norme CSS est pour moi assez révolutionnaire ! Elle peut permettre d’envisager de se passer des frameworks CSS habituels, comme Bootstrap (qui lui aussi propose un système de grille !) tout en offrant des possibilités d’affichage et d’organisation des éléments très puissantes (avec une syntaxe HTML et CSS ultra-claire !). Elle est désormais pleinement supportée par les principaux navigateurs du marché, donc aucune raison de ne pas l’utiliser ;)