CSS3 Grid Layout
Article par Raphael (Eleveur de kiwiz, Strasbourg)
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 actuelllement maintenue par quatre contributeurs, dont trois personnes de Microsoft, ainsi que Daniel Glazman, le co-chairman CSS du W3C.
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 (actuellement en version beta) supporte aujourd'hui cette spécification. Mais les autres ténors (Mozilla, Webkit, Opera) 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. Il est notamment prévu sur Chrome 19.
Compatibilté navigateurs du module Grid Layout
| Navigateurs | Versions |
|---|---|
|
|
Internet Explorer 10+ |

Le positionnement par grille
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 |
grid-template |
déclaration d'un "canevas" de cellules nommées (optionnel) |
grid-rows, grid-columns |
déclaration des dimensions de lignes et colonnes |
grid-row, grid-column |
placement d'un élément dans une ligne ou une colonne |
grid-cell |
positionnement d'un élément au sein d'une cellule nommée |
grid-row-span, grid-column-span |
distribution sur plusieurs lignes ou colonnes |
grid-row-align, grid-column-align |
alignement horizontal ou vertical |
grid-layer |
niveau du plan pour éléments superposés |
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. 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, sous réserve qu'ils soient originellement de type "block", seront automatiquement affectés par ce contexte particulier et pourront se placer au sein des "cellules" (grid-cell) de la trame.
Exemple 1 (affichage de deux blocs sur une ligne) :
<body>
<nav>nav</nav>
<section>section</section>
</body>
body {
display: grid;
grid-columns: 250px 300px;
}
nav {
grid-column: 1; /* placement en colonne 1 */
}
section {
grid-column: 2; /* placement en colonne 2 */
}

Note compatibilité : le module "Grid Layout", encore en brouillon (Working Draft), ne fonctionne actuellement que sur IE10 et nécessite des préfixes vendeurs -ms- pour être appliqué (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-columns: 250px 400px;
grid-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;
}

Variante : la syntaxe de templates
Grid Layout autorise la visualisation sous forme de canevas, en nommant explicitement les emplacement de la grille à l'aide de lettres de l'alphabet.
Cette variante n'est actuellement reconnue par aucun navigateur, c'est pourquoi les tests demeurent ardus à réaliser, mais en voici le concept général :
Exemple 3 (template) :
#inGrid {
display: grid;
grid-template: "hh"
"nc"
"ff";
}
#inGrid nav {
grid-cell: "n"; /* placement de <nav> dans l'emplacement "n" */
}

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") :
html, body {height: 100%;}
body {
display: grid;
grid-columns: 250px 1fr; /* largeur 250px et "espace restant" */
grid-rows: 100px 1fr;
}
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;
}

Centrer les éléments
Grid Layout permet d'aligner les contenus verticalement ou horizontalement à l'aide des propriétés grid-row-align et grid-column-align dont les valeurs 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) :
html, body {height: 100%;}
body {
display: grid;
grid-columns: 250px 250px;
grid-rows: 250px 250px;
}
nav {
grid-column: 1; grid-row: 1;
}
section {
grid-column: 2; grid-row: 1;
grid-row-align : center;
}
article {
grid-column: 1; grid-row: 2;
grid-column-align : center;
}
aside {
grid-column: 2; grid-row: 2;
grid-row-align : center;
grid-column-align : center;
}

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.
Les propriétés CSS grid-row-span et grid-column-span sont chargées d'organiser cette distribution sur plusieurs lignes ou colonnes.
Exemple 6 (column span) :
header {
grid-column: 1; grid-row: 1;
grid-column-span: 2;
}
nav {
grid-column: 1; grid-row: 2;
}
section {
grid-column: 2; grid-row: 2;
}

Le pseudo-élément ::grid-cell
Le pseudo-élément ::grid-cell offre la faculté de nommer un emplacement de la grille de manière très intuitive afin d'y placer un élément.
Ce pseudo-élément n'est encore supporté par aucun navigateur.
Exemple 7 (cellules nommées) :
body {
display: grid;
grid-columns: 300px 300px;
grid-rows: 200px 300px;
}
body::grid-cell("nav") { /* la position "nav" sera en 1ère colonne, 2ième ligne */
grid-column: 1; grid-row: 2;
}
body nav {
grid-cell: "nav"; /* on se positionne dans "nav" */
}
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").
Par exemple, si je souhaite répéter le motif de colonnes (50px 1em) dix fois dans la grille, j'écrirai grid-columns: (50px 1em)[10]
Exemple 9 (patterns) :
body {grid-columns: 10px (1fr 10px)[4];}
/* correspond à 10px 1fr 10px 1fr 10px 1fr 10px 1fr 10px */

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 10 (adaptation aux petits écrans) :
body {
display: grid;
grid-template: "abcd";
}
@media (max-width: 640px) {
body {
display: grid;
grid-template: "a"
"b"
"c"
"d";
}
}

Conclusion et usage
Vu la compatibilité navigateurs quasi inexistante du module Grid Layout, 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 (mais il faudra attendre de passer à Windows 8), et les autres navigateurs vont sans nul doute lui emboîter le pas rapidement.
Rendez-vous dans quelques années ? :)
Pour aller plus loin sur ce sujet, je vous invite à consulter un exposé (PDF) que j'ai présenté le 8 février 2012 lors du cycle de conférences MS TechDays, concernant le module Grid Layout ainsi que deux autres avancées CSS3.
Ressources
Commentaires
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.




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