- CSS Grid est largement pris en charge par les principaux navigateurs depuis mars 2017, mais
grid-template-areas reste encore sous-utilisé, alors qu’il permet de représenter visuellement une mise en page directement dans le CSS sans avoir à calculer les numéros de ligne
grid-template-areas fonctionne en plaçant des noms de zone dans des chaînes de caractères, puis en reliant les éléments enfants via grid-area ; un même nom doit obligatoirement former une zone rectangulaire
- Les lignes de grille nommées consistent à attribuer des noms aux lignes, comme
content-start / content-end, et le motif *-start / *-end peut être exploité par le navigateur comme une zone implicite
- Pour des cartes inversées, des en-têtes responsives, des mises en page éditoriales, des publications de style Threads, des cartes superposées ou des mises en page conditionnelles avec
:has(), on peut gérer des variantes de placement simplement en changeant les chaînes de zones du parent
- Chrome, Safari et Firefox proposent tous des DevTools pour les zones Grid, et Firefox est particulièrement utile grâce à l’affichage des noms de zones et à l’autocomplétion des noms de ligne possibles lors de l’édition de
grid-area
Rendre une mise en page plus lisible avec grid-template-areas
- Les mises en page CSS Grid classiques utilisent souvent des déclarations explicites de numéros de ligne, comme
grid-column: 1 / 3
- Les numéros de ligne ne sont pas visibles avant inspection dans les DevTools, et dans une mise en page avec lignes et colonnes, il est difficile de calculer mentalement les bons numéros
- Avec
grid-template-areas, chaque cellule reçoit un nom, ce qui fait apparaître le CSS lui-même comme une carte de la mise en page
.page {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-areas: "item1 item2";
gap: 1rem;
}
.item-1 {
grid-area: item1;
}
.item-2 {
grid-area: item2;
}
- Les éléments enfants sont associés aux zones nommées via
grid-area
- Dans l’exemple de carte, une définition comme
"featured featured article" permet à la zone featured d’occuper 2 colonnes et à la zone article d’en occuper 1
Syntaxe et règles à respecter absolument
grid-template-areas accepte une ou plusieurs chaînes de zones
- Une seule chaîne crée une mise en page unidimensionnelle avec uniquement des colonnes
- Plusieurs chaînes composent une mise en page multidimensionnelle avec lignes et colonnes
- Lorsqu’on utilise plusieurs chaînes, les écrire sur plusieurs lignes rend la mise en page plus facile à lire
.element {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-areas:
"aside main"
"footer footer";
}
- Chaque chaîne représente une ligne de la grille, qu’on peut envisager comme un tableau
- Les zones définies avec le même nom doivent former un rectangle dans le code
/* invalid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"header footer";
}
/* valid */
.layout {
grid-template-areas:
"header header"
"sidebar main"
"sidebar footer";
}
- Toutes les lignes doivent contenir le même nombre de jetons de zone, et même si une zone n’est pas utilisée, la cellule elle-même doit être définie
- Les cellules vides peuvent être représentées par un point ou plusieurs points
.element {
grid-template-areas:
"aside main"
"... footer";
}
- Le point est le null cell token de la spécification CSS Grid, qui représente une cellule de grille vide
Relation entre lignes de grille nommées et zones
- En CSS Grid, il y a toujours une ligne de plus que le nombre de colonnes
- Avec 3 colonnes, on obtient 4 lignes de grille
- Les lignes de grille nommées permettent d’attribuer un nom unique à une ligne au lieu d’utiliser uniquement des numéros
.layout {
grid-template-columns:
[full-start] 1fr
[content-start] 2fr
[content-end] 1fr [full-end];
}
.item {
grid-column: content-start / content-end;
}
- Nommer les lignes n’empêche pas de continuer à utiliser les lignes numérotées
- La taille de piste (track size) correspond à la taille d’une colonne ou d’une ligne ; des valeurs comme
1fr 1fr sont des tailles de piste
- Avec les lignes nommées, on nomme les lignes autour des pistes
.layout {
display: grid;
grid-template-columns:
[aside-start] 200px [aside-end main-start] 1fr [main-end];
}
- Une même ligne peut porter plusieurs noms ; dans l’exemple ci-dessus,
aside-end et main-start désignent la même ligne
- Si l’on définit des noms comme
aside-start et aside-end, le navigateur peut autoriser un usage comme grid-column: aside via des noms de ligne implicites
- Il n’est pas nécessaire de nommer toutes les lignes ; on peut ne nommer que les plus importantes
- Lors du placement, on peut mélanger numéros et noms, par exemple
grid-column: 1 / content-end
Gérer les variantes de placement avec les chaînes de zones du parent
- Avec
grid-template-areas, on peut modifier toute la mise en page en ne changeant que les chaînes de zones du parent, tout en conservant les mêmes noms grid-area sur les éléments enfants
.aside {
grid-area: aside;
}
.main {
grid-area: main;
}
.footer {
grid-area: footer;
}
- En gardant les mêmes noms
aside, main et footer, il suffit de changer les chaînes grid-template-areas pour que toute la disposition soit mise à jour automatiquement
- Le contrôle de la mise en page est centralisé dans la définition des zones du parent, ce qui facilite les ajustements
Inverser l’orientation d’une carte
- Avec Flexbox, il est facile d’inverser l’orientation d’une carte via
flex-direction: row-reverse
- Avec CSS Grid et des numéros de ligne, changer le sens oblige à modifier à la fois la définition des colonnes et les valeurs
grid-column de chaque enfant
- Avec des zones nommées, il suffit d’attribuer des zones à l’image et au contenu de la carte, puis de changer l’ordre des zones dans le parent
.card {
display: grid;
grid-template-columns: 150px 1fr;
grid-template-areas: "thumb content";
}
.card__thumb {
grid-area: thumb;
}
.card__content {
grid-area: content;
}
.card--flip {
grid-template-columns: 1fr 150px;
grid-template-areas: "content thumb";
}
- La même disposition peut aussi être exprimée avec la propriété raccourcie
grid-template
.card--flip {
grid-template: "content image" / 1fr 150px;
}
- La propriété raccourcie reste facultative, et certains préfèrent la version longue, jugée plus lisible
Mise en page d’en-tête responsive
- Un en-tête avec un logo, une navigation et une zone d’actions peut au départ être composé de 3 colonnes de taille identique
- Avec des numéros de ligne, il faut définir
grid-column séparément pour .logo, .nav et .actions
- Avec des noms de zone, on associe chaque enfant à
logo, nav et actions, puis on ne change que grid-template-areas du parent selon le viewport
.header {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "logo nav actions";
}
.logo {
grid-area: logo;
}
.nav {
grid-area: nav;
}
.actions {
grid-area: actions;
}
- Sur de petites largeurs, on peut placer le logo et les actions sur la première ligne, puis la navigation sur toute la largeur
.header {
grid-template-areas:
"logo logo actions"
"nav nav nav";
}
- À partir de
380px, on peut placer le logo à gauche et la navigation avec les actions à droite
@media (min-width: 380px) {
.header {
grid-template-areas:
"logo nav nav"
"logo actions actions";
}
.nav {
justify-self: end;
}
}
- À partir de
900px, on peut revenir à une disposition sur une seule ligne
@media (min-width: 900px) {
.header {
grid-template-areas: "logo nav actions";
}
}
- Les chaînes de zones agissent comme un mapping qui montre directement l’agencement de l’interface dans le CSS
Exemple de mise en page éditoriale
- Une section contenant un titre, du texte et une image peut facilement adapter sa disposition selon la taille du viewport avec
grid-template-areas
.section {
display: grid;
grid-template-areas:
". title title"
"thumb content content";
gap: 1rem;
}
- Le point à gauche du titre représente un espace vide, c’est le null cell token
- Dans un exemple de section inspiré du style de time.com, on utilise les zones
feature, secondary et most-read ainsi que des colonnes vides de chaque côté
.featured-section {
display: grid;
grid-template-areas:
". feature most-read ."
". secondary most-read .";
grid-template-columns: 1fr minmax(auto, 57.313rem) minmax(12rem, 18.75rem) 1fr;
grid-template-rows: minmax(auto, 25rem) 1fr;
}
- Les colonnes vides de chaque côté servent surtout de marges gauche et droite
- Dans la version responsive,
feature, secondary et most-read sont empilés verticalement sur petit écran, puis les colonnes et les zones sont redéfinies à partir de 500px et 900px
grid-template-rows peut être remplacé par la définition des zones et n’est donc pas indispensable
Composant de publication de style Threads
- En examinant le CSS de Threads app by Meta, on peut voir un cas d’usage de CSS Grid pour un composant de publication
- Dans l’exemple d’origine, les éléments sont placés avec
grid-template-columns, grid-template-rows et des numéros de ligne
.postBody {
grid-column-start: 2;
grid-row-start: 2;
grid-row-end: span 3;
}
- Plusieurs variantes de publication peuvent être exprimées plus simplement avec
grid-template-areas
.post {
grid-template-areas:
"avatar header"
"avatar body"
". body"
". footer";
}
.post--reply {
grid-template-rows: 40px max-content max-content;
grid-template-areas:
"avatar header"
"body body"
"body body"
"footer footer";
}
.post--nested {
grid-template-areas:
"avatar header"
"avatar body"
"line body"
"footer footer";
}
- Il suffit de regarder les chaînes de zones pour distinguer les variantes par défaut, réponse et publication imbriquée
Éléments superposés et noms de zone
- Dans
grid-template-areas, un même nom doit former un rectangle ; répéter le même nom dans une forme non rectangulaire rend la déclaration invalide
.layout {
display: grid;
grid-template-columns: 1fr 1fr fr;
grid-template-areas:
"card tag tag"
"title title card";
}
- Dans cet exemple,
card ne forme pas un rectangle et la déclaration est donc invalid
- Pour des cartes superposées, on peut définir de nouveaux noms de zone comme
thumb-1 et thumb-2, puis les utiliser dans grid-column et grid-row
.card {
display: grid;
grid-template-columns: auto auto 1fr;
grid-template-rows: auto auto;
grid-template-areas:
"thumb-1 tag"
"title thumb-2";
}
.thumb {
grid-column: thumb-1 / thumb-2;
grid-row: thumb-1 / thumb-2;
}
- Le tag et le titre peuvent chacun être placés avec
grid-area, puis alignés avec align-self et justify-self
- Si nécessaire, il faut aussi gérer l’ordre d’empilement des enfants, mais dans l’exemple, l’ordre source suffit
- Cet exemple de superposition est inspiré de la page Oddbird’s Cascading Layouts
:has() et mise en page conditionnelle
- En combinant le sélecteur CSS
:has() et les zones Grid, on peut changer la mise en page selon la présence ou l’absence de certains éléments
- On peut appliquer des définitions de zones différentes selon qu’un
<figure> contient ou non un figcaption
figure {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-areas: "img img img";
gap: 0.5rem;
}
img {
grid-area: img;
}
figcaption {
grid-area: caption;
}
.card:has(figcaption) {
grid-template-areas:
"img img caption"
"img img .";
}
Prise en charge des directions multilingues LTR/RTL
- CSS Grid ajuste la mise en page selon que la page est en LTR ou en RTL
- Les zones de grille nommées suivent elles aussi la direction de la page ; la mise en page s’inverse donc en configuration RTL
- Pour aller plus loin sur la création de mises en page RTL, on peut consulter le guide RTL Styling 101
Différences de prise en charge dans les DevTools
- Chrome, Safari et Firefox proposent tous des DevTools pour les zones Grid
- Chrome
- Place les noms de zone en haut à gauche, ce qui peut les faire se chevaucher visuellement
- L’overlay coloré peut modifier la façon dont le design apparaît
- Safari
- Le contour rose aide à distinguer clairement les éléments
- Permet de voir les noms de ligne
- L’affichage des noms de ligne pourrait encore être amélioré, notamment dans la manière dont ils s’empilent
- Firefox
- Affiche les noms de zone plus clairement que Chrome et Safari
- Propose une liste d’autocomplétion lors de la saisie de noms personnalisés comme
*-start et *-end
- Fournit la liste de tous les noms de ligne possibles lors de l’édition de
grid-area sur un élément enfant
Ressources de référence
1 commentaires
Avis sur Hacker News
La démo animée était assez intéressante, mais déception en découvrant que cette animation n’était pas faite en CSS
Après avoir appris Flexbox, je me suis dit que « ça suffisait », et je n’ai pas approfondi Grid. Il semble y avoir des raisons de préférer Grid [0], mais globalement je n’ai jamais eu besoin de faire quelque chose qui ne soit possible qu’avec Grid, et pour les tableaux de données j’utilise de vrais
<table>[0] https://css-tricks.com/css-grid-replace-flexbox/
Je n’ai utilisé Grid que pour des galeries d’images responsives comme https://labs.jensimmons.com/2016/examples/image-gallery-grid... ou des cartes responsives comme https://every-layout.dev/demos/grid-cards/.
grid-template-columnsvaut la peine d’être appris, etgrid-gapest pratique. Pour le reste, j’ai l’impression que Flexbox gère presque toutEn revanche,
grid-template-areasreste encore un peu flou pour moi. L’article avance que c’est plus simple pour ajuster la mise en page selon les breakpoints ou quand « un membre de l’équipe doit modifier la mise en page », mais je ne suis peut-être tout simplement pas le public viséOn peut utiliser les deux selon les besoins, et combinés, ils deviennent un outil de mise en page très puissant
https://www.youtube.com/watch?v=MWWcZzossc8
Attends,
1/3n’est pas une fraction mais une plage de 1 à 3 ? Je ne comprends pas pourquoi ils ont choisi cette syntaxe. Il existe en programmation beaucoup de syntaxes raisonnables et bien connues pour représenter des plages, par exemple1..3Il me semble qu’une bonne partie des problèmes que les programmeurs rencontrent avec CSS vient de ce malentendu
!importantne veut pas dire « pas important », mais « important ! »Je n’ai jamais vraiment maîtrisé ni Grid ni Flexbox. La dernière stratégie de mise en page que je maniais à peu près correctement était float. Cet article m’a donné la confiance nécessaire pour essayer CSS Grid dans ma prochaine mise en page, et il est aussi très bien fait
Il existe beaucoup de bons articles, mais ces deux articles de CSS-Tricks m’ont suffi
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
https://css-tricks.com/snippets/css/complete-guide-grid/
En plus des articles CSS-Tricks déjà cités, je recommande le guide Flexbox de MDN [1] et la référence « CSS flexible box layout » [2]. Ils m’ont aidé à comprendre plus en profondeur les concepts derrière Flexbox, ses propriétés et le fonctionnement réel des propriétés raccourcies
[1]: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...
[2]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexibl...
Cela dit, Flexbox reste proche d’une mise en page unidimensionnelle pouvant passer à la ligne, donc l’astuce consiste à imbriquer et empiler. Grid, avec ses templates et ses enfants directs qui occupent des zones prédéfinies, est plus statique que Flexbox, et il a pour limite de ne pas affecter les éléments imbriqués à l’intérieur. Mais subgrid semble devoir changer cela
Ressources associées :
Grid Garden https://cssgridgarden.com
Flexbox Froggy https://flexboxfroggy.com
J’aimerais qu’il existe une version encore plus basique que ce document, une sorte d’« avant l’introduction ». Je suis resté bloqué dès la partie d’introduction et je n’ai pas réussi à avancer. En particulier, dans le passage « pour placer les éléments enfants dans une Grid, il faut indiquer le numéro de ligne de chaque élément avec
grid-column», je ne comprenais pas ce que signifiait numéro de ligne iciJ’ai essayé de continuer en me disant que je comprendrais avec le contexte, mais je me suis retrouvé bloqué aussitôt sur des expressions comme
1 / 3ou1 / 4|a||b|, les deux lignes du milieu comptent en réalité comme une seule, donc il y en a 3 au totalAinsi,
1/3n’est pas une fraction mais une plage de colonnes, et signifie « commence à la ligne 1 et se termine à la ligne 3 »Le nom « numéro de ligne » n’est pas très heureux, mais en pratique il s’agit des bords des colonnes. Donc
1/3va du bord n° 1, c’est-à-dire tout à gauche, jusqu’au bord n° 3, et occupe les 2 colonnes entièresPour CSS Grid, je recommande vivement Jen Simmons Mondrian with auto flow. Il suffit d’aller sur https://labs.jensimmons.com/2017/01-011.html, d’appuyer sur
CetD, puis de redimensionner la fenêtre. Il y a aussi une vidéo YouTube à regarder avec : https://www.youtube.com/watch?v=qNtJ5p3h2A4C’est vraiment superbe
Ce que j’aimerais encore comprendre avec auto flow, c’est comment détecter et remplir les espaces vides. Quand on a des objets de tailles variées disposés aléatoirement, comment faire pour qu’auto flow ne laisse pas de trous ? Ou bien peut-on détecter les trous et y ajouter quelque chose ?
J’espère que la question n’est pas idiote, mais pourquoi la syntaxe a-t-elle été définie avec une barre oblique, comme
1/2ou3/4? Quelque chose comme1-2, de la colonne 1 à la colonne 2, ou1->2, ne serait-il pas plus naturel ?1--1,1->-1ou1/-1?En CSS, les valeurs sont déjà séparées par des espaces, et si l’on tient compte aussi de l’intuition qu’on associe généralement aux tirets, les formes ci-dessous sont nettement préférables
grid-column: 4 somegridarea / 6;grid-column: span 3 / 6;grid-column: span somegridarea / span someothergridarea;C’est beaucoup plus clair que d’écrire ceci
grid-column: 4 somegridarea-6;grid-column: span 3-6;grid-column: span 3->6;grid-column: span somegridarea-span someothergridarea;grid-column: span somegridarea->span someothergridarea;J’aime vraiment ce genre de billets de blog interactifs. Pour Grid, je recommande vivement de manipuler directement les grid areas dans un outil comme https://grid.layoutit.com/
J’utilise ce site depuis des années pour planifier des mises en page Grid, et cela rend l’ajustement des espacements beaucoup plus facile
C’est peut-être la première fois que je comprends réellement CSS Grid. L’affichage des numéros aide énormément, et c’est un article auquel je reviendrai souvent
J’aime CSS Grid et le concept de zones, mais je pense que la partie la plus difficile reste la gestion du responsive, surtout entre les tailles mobile et desktop. Selon quels éléments d’UI doivent être ouverts, ou s’ils doivent occuper tout l’écran, il faut souvent mettre à jour
grid-template-areaainsi que la taille des lignes/colonnes en JavaScriptJe n’ai pas encore trouvé de monde où
minmaxoucalcsuffisent à résoudre ça, et j’aimerais que quelqu’un connaisse la réponsevar(--foo), plutôt que dans des valeurs fixesAinsi, côté JavaScript, il suffit de mettre à jour la valeur de cette variable, et Grid la prend en compte
display: noneà cette tailleExemple très simple : https://codepen.io/trescenzi/pen/vYqpjvL
:has()ou subgrid pourraient résoudre le problème, mais je n’ai pas beaucoup d’expérience directe