CSS

CSS3 Grid Layout

Article par (Intégrateur du Dimanche, Strasbourg)
Créé le , mis à jour le (65555 lectures)
Tags : css, positionnement, grille, grid, css3

Le module de positionnement "Grid Layout" est une spécification du W3C à l'état de brouillon (Working Draft) dont les premiers jets datent de 2004.

Sa documentation officielle est actuellement maintenue par trois contributeurs, dont une personne de Microsoft et une personne de Google.

Note : ce tutoriel a été initialement rédigé en février 2012. Il a subi une grosse refonte en octobre 2015 pour se mettre à jour.

Avertissement La compatibilité de ce module est pour le moins ténue à l'heure actuelle : comme en témoigne l'excellente ressource Can I Use, seul... Internet Explorer 10+ supporte aujourd'hui cette spécification par défaut.

Mozilla Firefox, Chrome et Opera nécessitent d'activer un "flag" dans la configuration du navigateur; les autres navigateurs sont également intéressés et ne devraient pas tarder à implémenter ce module, au regard des vastes possibilités offertes par ce schéma de positionnement.

Comment activer les flags ?

  • Sur Firefox : about:config puis layout.css.grid.enabled
  • Sur Chrome : chrome://flags/ puis "Activer les fonctionnalités expérimentales de Web Platform"

Compatibilté navigateurs du module Grid Layout

Navigateurs Versions Détails
Internet Explorer Internet Explorer 10+
IE mobile 10+
Avec préfixe -ms-
Firefox Firefox 40+

Activation de Grid Layout via un flag. Pas de préfixe.

Chrome Chrome 29+ Activation de Grid Layout via un flag. Pas de préfixe.
Opera Opera 28+ Activation de Grid Layout via un flag. Pas de préfixe.

Le positionnement par grille

the grid

Le concept général de Grid Layout (ou "positionnement en grille") est de diviser virtuellement l'espace en zones majeures dans une page ou une application. Concrètement et schématiquement, il s'agira de découper en lignes et en colonnes comme nous le ferions pour un tableau de mise en page.

On y trouve d'ailleurs de nombreuses références d'affichage "tabulaire" avec lignes et colonnes, rowspan et colspan. En cela, ce schéma de positionnement est très similaire aux tableaux HTML ou aux rendus de type display: table, display: table-cell et autre display: table-row.

Mais la différence la plus flagrante est que la grille consiste en une construction de l'esprit et ne nécessite aucun élément HTML ni balisage pour être élaborée. Aucune charpente physique telle que <table>, <tbody>, <tr>, <td> ou <th> n'est nécessaire, ce qui en facilite l'adaptation à différentes tailles d'écrans et de périphériques : inutile d'intervenir sur l'ordre, la nature ou la "sémantique" des éléments HTML, il suffit de modifier le canevas initial pour qu'ils s'y adaptent.

Les propriétés usuelles de Grid Layout

Propriété Détails
grid, inline-grid déclaration d'un contexte de grille (création d'un "grid-container")
grid-template-areas déclaration d'un "canevas" de cellules nommées (optionnel)
grid-template-rows, grid-template-columns déclaration des dimensions de lignes et colonnes
grid-row, grid-column placement d'un élément "grid-item" dans une ligne ou une colonne
grid-gap, grid-column-gap, grid-row-gap espaces inter-colonnes ou inter-rangées (gouttières)
align-items, justify-items alignement horizontal ou vertical
align-self, justify-self alignement horizontal ou vertical d'éléments distincts

Mise en oeuvre

On crée un "contexte de grille" tout simplement en appliquant la déclaration display: grid à un élément conteneur qui constituera la trame générale, il deviendra un "grid-container" et ses enfants directs des "grid-items". Cette trame sera définie par un schéma virtuel formé de lignes et colonnes définissant des "cellules".

Tous les enfants (directs) de ce conteneur général seront automatiquement affectés par ce contexte particulier et pourront se placer au sein des "cellules" de la trame.

Exemple 1 (affichage de deux blocs sur une ligne) :

<body>
  <nav>nav</nav>
  <section>section</section>
</body>
body {
  display: grid;
  grid-template-columns: 200px 400px;
}
nav {
  grid-column: 1; /* placement en colonne 1 */
}
section {
  grid-column: 2; /* placement en colonne 2 */
}

Grid 01

Démonstration

Note compatibilité : le module "Grid Layout", encore en brouillon (Working Draft), ne fonctionne actuellement que sur certains navigateurs, et parfois avec préfixes uniquement. Par exemple IE10+ nécessite des préfixes vendeurs -ms- pour être focntionnel (par exemple : display: -ms-grid, ou -ms-grid-row: 2). Sur cette page, nous ne mentionnons que la syntaxe finalisée sans préfixe, mais vous devrez les ajouter pour vos tests.

Exemple 2 (grille de 4 emplacements) :

<body>
  <nav>nav</nav>
  <section>section</section>
  <article>article</article>
  <aside>aside</aside>
</body>
body {
  display: grid;
  grid-template-columns: 250px 400px;
  grid-template-rows: 100px 300px;
}
nav {
  grid-column: 1; grid-row: 1;
}
section {
  grid-column: 2; grid-row: 1;
}
article {
  grid-column: 1; grid-row: 2;
}
aside {
  grid-column: 2; grid-row: 2;
}

Grid 02

Démonstration

Variante : la syntaxe de templates

Grid Layout autorise la visualisation sous forme de canevas, en nommant explicitement les emplacements de la grille à l'aide de chaînes de caractères ou de simples lettres.

Exemple 3 (template) :

#inGrid {
  display: grid;
  grid-template-areas: "h h"
                       "n c"
                       "f f";
}
nav {
  grid-area: n; /* placement de <nav> dans l'emplacement "n" */
}

Grid 03

Démonstration

Les unités de largeur et hauteur

Le modèle d'affichage en grille ne se contente pas d'employer les unités de largeur et hauteur habituelles; il introduit des fonctions complexes permettant de s'adapter à des contextes de contenus différents :

Unité Détails
px, %, em, ex, rem,… pixels, pourcentages, em,… (unités courantes)
fr fraction(s) de l'espace restant
min-content se rapporte à la largeur (ou hauteur) de l'élément le plus petit
max-content se rapporte à la largeur (ou hauteur) de l'élément le plus grand
minmax(min, max) exemple minmax(min-content, 20%) correspond à largeur 20% (ou hauteur), mais au minimum largeur (ou hauteur) du contenu
auto s'adapte à la largeur (ou hauteur) du contenu
fit-content identique à auto et aussi à minmax(min-content, max-content)

Exemple 4 (illustration de l'unité "fr") :

body {
  display: grid;
  grid-template-columns: 250px 1fr; /* 250px + "largeur restante" */
  grid-template-rows: 100px 1fr; /* 100px + "hauteur restante" */
}
nav {
  grid-column: 1; grid-row: 1;
}
section {
  grid-column: 2; grid-row: 1;
}
article {
  grid-column: 1; grid-row: 2;
}
aside {
  grid-column: 2; grid-row: 2;
}

Grid 04

Démonstration

Centrer les éléments

Par défaut, les éléments "grid-items" s'étirent pour occuper tout l'espace de leur cellule.

Cependant, Grid Layout permet d'aligner les contenus verticalement ou horizontalement à l'aide des propriétés suivantes :

Propriété Détails
justify-items alignement au sein d'une cellule (dans l'axe principal). S'applique au conteneur
justify-self alignement d'un grid-item au sein de sa cellule. S'applique au grid-item
align-items alignement au sein d'une cellule (dans l'axe secondaire). S'applique au conteneur
align-self alignement d'un grid-item au sein de sa cellule. S'applique au grid-item

Les valeurs de ces propriétés peuvent être les suivantes :

Valeur Détails
start aligne l'élément au début de la cellule (gauche ou droite selon le sens de la lecture)
end aligne l'élément à la fin de la cellule (gauche ou droite selon le sens de la lecture)
center place l'élément au centre de la cellule
stretch étire l'élément (ses marges) pour occuper tout l'espace dans la cellule

Exemple 5 (multiples centrages) :

body {
  display: grid;
  grid-template-columns: 200px 200px;
  grid-template-rows: 200px 200px;
  grid-template-areas: "a b" "c d";
}
header {
  grid-area: a;
  justify-self: center;
}
nav {
  grid-area: b;
  align-self: center;
}
article {
  grid-area: c;
  justify-self: center;
  align-self: center;
}
footer {
  grid-area: d;
}

 

Grid 05

Démonstration

Occuper plusieurs emplacements

Tels les célèbres attributs rowspan et colspan dédiés aux tableaux HTML, le module Grid Layout introduit la possibilité à un élément de s'étaler sur plusieurs emplacements, à la fois horizontalement et verticalement.

Le descripteur CSS span est chargé d'organiser cette distribution sur plusieurs lignes ou colonnes. Par défaut, un grid-item dispose d'un span de valeur 1.

Exemple 6 (column span) :

.container {
  display: grid;
  grid-template-columns: 10em 1fr;
  grid-template-rows: min-content 1fr min-content;
  height: 300px;
}
header {
  grid-column: 1  / span 2; 
  grid-row: 1;
}
nav {
  grid-column: 1; 
  grid-row: 2;
}
article {
  grid-column: 2; 
  grid-row: 2;
}
footer {
  grid-column: 1  / span 2; 
  grid-row: 3;
}

Grid 06

Démonstration

Les motifs de répétition

Une fonctionnalité particulièrement intéressante du positionnement sous forme de grilles est de pouvoir appliquer des motifs de répétition de colonnes ou de lignes (appelés "patterns").

La notation repeat() est faite pour ça.

Par exemple, si je souhaite répéter le motif de colonnes (50px 1em) dix fois dans la grille, j'écrirai grid-template-columns: repeat(10, 50px 1em)

Exemple 7 (patterns) :

.container {
  display: grid;
  grid-template-columns: 10px repeat(4, 1fr 10px);
}
header {
  grid-column: 2 ;
}
nav {
  grid-column: 4; 
}
article {
  grid-column: 6; 
}
footer {
  grid-column: 8; 
}

 

Grid 07

Démonstration

Répartition automatique

Au sein de leur grid-container, les éléments grid-items se répartissent automatiquement par défaut. C'est à dire que si aucune place ne leur est assignée, ils se disposent dans le premier emplacement disponible au sein de la grille, dans le sens horizontal.

Il est possible de modifier ce comportement à l'aide de la propriété grid-auto-flow, dont les valeurs peuvent être :

  • row : répartition automatique rangée par rangée (valeur par défaut)
  • column : répartition automatique colonne par colonne

Exemple 8 (grid-auto-flow: column)

.container {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-template-rows: 100px 100px 100px;
  grid-auto-flow: column;
}

Grid 08

Démonstration

Vous avez dit "responsive" ?

Pour finir cette présentation du modèle de positionnement Grid Layout en apothéose, j'ai gardé le meilleur pour la fin.

L'un des avantages les plus flagrants d'une grille virtuelle, indépendante des éléments HTML qui peuvent s'y placer, est qu'il est extrêmement aisé de modifier la grille selon le contexte. Par exemple, pour s'adapter immédiatement aux différentes tailles d'écran, il suffit de... changer la grille initiale.

Associé aux CSS3 Media Queries, le modèle de positionnement en grille donne toute sa puissance, plus particulièrement si vous avez opté pour une trame sous forme de variante "template". En effet, seul le patron de départ nécessite d'être modifié : inutile d'intervenir sur la structure HTML, ni même sur le positionnement de chaque élément de page.

Exemple 09 (adaptation aux petits écrans) :

.container {
  display: grid;
  grid-template-areas: "a b c d";
  grid-template-columns: repeat(4, 1fr)
}

/* Responsive */
@media (max-width: 640px) {
  .container {
    grid-template-areas: "a" "d" "b" "c";
    grid-template-columns: 1fr;
  }
}

 

Grid 09

Démonstration

Conclusion et usage

Vu la faible compatibilité navigateurs du module Grid Layout actuellement, il est bien entendu utopique d'employer ce type de positionnement en production à l'heure actuelle, même sur des périphériques avant-gardistes.

Cependant, la simplicité et la robustesse de ce schéma lui promet un bel avenir : Microsoft a ouvert la voie, et les autres navigateurs sont en train de lui emboîter le pas rapidement.

Rendez-vous dans quelques années ? :)

Pour aller plus loin sur ce sujet, je vous invite à consulter le site gridbyexample.com de Rachel Andrew (en anglais), entièrement consacré à Grid Layout et contenant de nombreuses ressources et exemples concrets..

Ressources

Commentaires

Luleen a dit le

Ca serait extra que ce soit supporté par tous les navigateurs !
Ca faciliterait tellement de choses lol

glow a dit le

Bel article Raphael. Vivement l'implémentation plus généralisée des grid layout !

pchlj a dit le

Et avant d'en arriver là... si déjà ça :

display: table, display: table-cell et autre display: table-row.

c'était supporté !!! ça serait vraiment génial !!

Raphael a dit le

@pchlj : "table-*" (CSS2) est supporté depuis pas mal de temps. Seuls IE6 et IE7 ne le supportent pas ;)

oh!rocks a dit le

Pour une fois, Microsoft est en avance sur tout le monde... :D

chris_tofe a dit le

@oh!rocks : C'est pas faux! :) Pas contre, avant d'être en avance, il faudrait qu'il pense déjà à rattraper les nombreuses années de retard qu'il a face à la concurrence. Mais bon, il faut reconnaître que depuis IE9, Microsoft travaille dans le bon sens, même si tout n'est pas encore parfait!

kustolovic a dit le

Merci pour ces infos. ça fait rêver. reste plus qu'à trouver un moyen de simuler le principe des blocs liés (en PAO) et tout sera parfait^^.

Raphael a dit le

@kustolovic : ça existe déjà (en brouillon forcément) et ça s'appelle CSS3 Regions -> http://dev.w3.org/csswg/css3-regions/ ;)

Manumanu a dit le

@chris_tofe : Même depuis IE8 ; cette version n'avait rien à se reprocher. Ce qui lui a été reproché était le non support des nouvelles propriétés CSS3 et du html5, qui n'étaient à l'époque que des ébauches. Microsoft avait choisit de ne pas implémenter de propriétés expérimentales à base de -ms-, préférant se conformer aux standards actuels. Et alors qu'on leur avait toujours reproché de ne pas respecter les standards, il leur a été reproché de ne pas faire dans l'expérimental :)

Du reste, certaines propriétés nouvellement intégrées dans le CSS3, sont en réalité existantes depuis Internet Explorer 5... Comme quoi, être hors des standards, ça peut aussi apporter du bon un jour.

kustolovic a dit le

@raphael
*verse une larme
merci de l'info, je surveillerai cela de près!

@manumanu: ie8, certaines pseudo-classes css 2 non prises en comptes, certaines propriétés pas tout à fait conforme. Ils auraient pu faire un effort sur des "expérimentales" comme opacity.