Niveau Niveau confirmé

CSS3 Grid Layout

Articlecss

Publié par le , mis à jour le (224821 lectures)

positionnement créer un menu en css grille grid css3

Le module de positionnement "Grid Layout" est une spécification du W3C à l'état de Candidate Recommandation 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.

En février 2019 est sorti mon livre entièrement dédié à Grid Layout. Il se nomme "CSS3 Grid Layout : vous allez enfin aimer CSS" et je vous recommande bien évidemment sa lecture afin de comprendre tous les rouages de ce positionnement révolutionnaire, et d'en maîtriser tous les aspects.

Compatibilité navigateurs du module Grid Layout

Data on support for the css-grid feature across the major browsers from caniuse.com

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

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 fonctionnel (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..

Commentaires

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 !!

@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!

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^^.

@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.

@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.

Entre les float, les display table, les flexbox et les grid, il faudra faire attention très vite à ne pas prendre de mauvaises habitudes .
Si je suis ma logique :
- pour positionner un logo à droite et une navigation à gauche, on utilisera les float.
- pour disposer les éléments du menu lui même on partira sur du flexbox
- pour placer le header (contenant le logo et la nav), le container, le footer et la sidebar, on utilisera le grid-layout .
- pour créer un tableau on utilisera.... le display table ...

Mais quels atouts le grid-layout a t il comparé au display flex pour le responsive design ? C'est ça que je n'arrive pas à trouver .
Et le display-table .... utilisable uniquement pour les tableaux ?

@benjamin-derepas : Selon moi, un tableau doit être codé en html avec "table". CSS "display-table" sert à simuler le rendu d'un tableau, et est une possibilité de positionnement comme les autres que vous avez évoquées. Aussi, il semble qu'aucune technique ne soit meilleure qu'une autre, mais que certaines s'adaptent davantage à nos attentes.

Concernant l'atout de Grid Layout sur Flexbox, il semble reposer sur la possibilité d'un rendu en 2 dimensions : FB permettrait la disposition en lignes *ou* en colonnes, tandis que GL le permettrait en lignes *et* en colonnes (cf. notamment https://www.rachelandrew.co.uk/archives/2016/03/30/should-i-use-grid-or-flexbox/)

Bonjour et merci pour ce rappel. J'ai l'impression qu'aujourd'hui on peut l'utiliser en production non ?

Merci.

@Damino : "statistiquement" la réponse est sans aucun doute oui. Dans notre agence c'est le cas. Concrètement, cela dépend du public cible.