La Cascade

Un peu de tout sur CSS, HTML, SVG et JS,traduit du web anglophone
Rechercher

grid-template-areas

par Mojtaba Seyedi, 9 février 2023, css, cssgrid, dico, article original paru le 26 mai 2022 dans CSS-Tricks

Une explication très claire et détaillée de la propriété grid-template-area de CSS Grid par Mojtaba Sereyi.


La propriété CSS grid-template-areas permet de définir et de nommer les cellules (ou les zones de grille) d'un conteneur de grille CSS.

.grid-container {
  display: grid;
  grid-template-areas: 'header header' 'sidebar main';
}

Que fait le code ci-dessus ? Eh bien nous obtenons une grille de deux par deux dont la rangée supérieure réserve deux colonnes à une zone appelée "header". La rangée inférieure dispose également de deux colonnes, mais les réserve à des zones de la grille appelées respectivement sidebar et main.

Two by two grid of squares.

Notre grille est créée et nous avons défini des zones de grille, mais il n'y a rien d'assigné encore à ces zones. Si nous voulons placer un élément dans une zone de la grille, nous devons le déclarer explicitement avec la propriété grid-area sur cet élément :

.grid-container {
  display: grid;
  grid-template-areas: 'header header' 'sidebar main';
}
.grid-header {
  grid-area: header;
}
.grid-sidebar {
  grid-area: sidebar;
}
.grid-content {
  grid-area: main;
}

Il faut garder à l'esprit qu'une zone de grille doit être soit une cellule unique dans le conteneur de la grille, soit un groupe de cellules adjacentes de forme rectangulaire. Tous les exemples suivants sont valables :

Two valid and valid examples of grid areas.
Ces rectangles verts sont des exemples de grid template areas valides.

Mais nous ne pouvons pas former des zones de grille non rectangulaires. Donc, pas de chance si la zone que vous voulez définir a plutôt la forme d'un "T" ou d'un "L".

Two invalid examples of grid-template-areas.

Syntaxe

grid-template-areas: none | string
Initial value: none
Applies to: grid containers
Inherited: no
Computed value: as specified, the keyword none or a list of string values
Animation type: discrete

Valeurs

/* Keyword value */
grid-template-areas: none;

/* <string> values */
grid-template-areas: 'col-1 col-2 col-3';
grid-template-areas: 'header header header' 'sidebar main main';
grid-template-areas:
  'header header header'
  'sidebar main main'
  '. footer footer';

/* Global values */
grid-template-areas: inherit;
grid-template-areas: initial;
grid-template-areas: revert;
grid-template-areas: unset;

none

C'est la valeur par défaut. Comme vous l'avez sans doute deviné, none signifie qu'aucune zone de grille nommée ni aucune piste de grille explicite n'est définie dans le conteneur de grille. Ça signifie également que les pistes de la grille sont générées implicitement et que leurs tailles sont définies par les propriétés grid-auto-columns et grid-auto-rows.

Il existe en fait une autre façon de créer des pistes de grille explicites qu'en utilisant grid-template-areas, et c'est d'utiliser les propriétés grid-template-columns et grid-template-rows à la place. Nous y reviendrons plus en détail dans la suite de cet article.

string

Une chaîne de caractères (string) peut être n'importe quel nom que l'on souhaite donner à une zone spécifique du modèle de grille. Ainsi, si vous avez une rangée supérieure dans votre conteneur de grille et que vous voulez que l'en-tête de votre mise en page s'y trouve, vous pouvez nommer la zone "en-tête" ou "page-top" ou littéralement ce que vous voulez. En fait, s'il y a plusieurs colonnes dans cette rangée, nous pouvons donner à chacune d'elles un nom différent.

.grid {
  grid-template-areas: 'logo menu utility-nav';
}

On remarque que la totalité de la rangée de trois colonnes de cet exemple est entre guillemets. C'est essentiel, car les grid-template-area entre guillemets indiquent une nouvelle rangée. Ainsi, si nous avons deux rangées, nous verrons deux groupes entre guillemets :

.grid {
  grid-template-areas: 'logo menu utility-nav' 'sidebar-1 content sidebar-2';
}

Mieux encore, nous pouvons améliorer la lisibilité en écrivant chaque rangée sur sa propre ligne :

.grid {
  grid-template-areas:
    'logo menu utility-nav'
    'sidebar-1 content sidebar-2';
}

La syntaxe des chaînes de caractères permet de couvrir ou de sauter des cellules dans le conteneur de la grille. Nous y reviendrons dans un instant.

Utilisation de base

Tout d'abord, définissons les zones de grille en utilisant la propriété grid-template-areas dans le conteneur de grille parent :

.grid {
  display: grid;
  grid-template-areas:
    'header header header'
    'sidebar main main'
    'footer footer footer';
}

Dans l'état actuel des choses, le conteneur de grille comporte des zones nommées, mais rien à l'intérieur. Pour y placer des éléments, nous devons assigner la zone de grille nommée à un élément en utilisant la propriété grid-area sur l'élément que nous plaçons :

header {
  grid-area: header;
}

aside {
  grid-area: sidebar;
}

main {
  grid-area: main;
}

footer {
  grid-area: footer;
}

Voici le résultat basé sur les zones du modèle de grille que nous avons définies sur le conteneur de grille parent :

A webpage layout created using the CSS `grid-template-areas` property

Dimensionnement des zones nommées d'une grille

La taille des zones de la grille peut être définie à l'aide des propriétés grid-template-columns et grid-template-rows dans le conteneur de la grille parente.

Supposons que notre grille ait besoin de deux colonnes et que la deuxième colonne prenne deux fois plus d'espace que la première. Nous pouvons utiliser l'unité fraction (fr) pour cela :

.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr 2fr;
  grid-template-areas: 'sidebar main';
}

Il en va de même pour les rangées. Supposons maintenant que nous ayons besoin de la présentation suivante dans une grille de trois par trois :

A webpage layout created using the CSS grid-template-areas property

Cette fois-ci, les première et troisième rangées ont la même hauteur fixe de 250 pixels, mais la rangée du milieu est dimensionnée de manière à occuper autant d'espace que le contenu en a besoin :

.grid {
  display: grid;
  gap: 1rem;
  grid-template-rows: 250px auto 250px;
  grid-template-areas:
    'header header header'
    'sidebar main main'
    'footer footer footer';
}

Si vous vous demandez ce qu'il se passe avec toutes ces zones de gabarit de grille nommées à plusieurs reprises, il s'agit de...

...cellules et rangées qui s'étendent

La répétition d'une zone nommée relie les cellules. Ainsi, si l'objectif est de créer une zone nommée "feature" et qu'elle occupe deux colonnes dans la rangée supérieure, nous pouvons faire quelque chose comme ceci :

/* Valid declaration */
grid-template-areas: 'feature feature widget';

Cool, et nous pouvons faire la même chose dans le sens vertical si la même zone nommée commence chaque ligne :

/* Valid declaration */
grid-template-areas:
  'feature aside widget-1'
  'feature aside widget-2';

Bien entendu, nous pouvons combiner les deux pour obtenir une zone de gabarit qui s'étend dans les deux directions :

/* Valid declaration */
grid-template-areas:
  'feature feature widget-1'
  'feature feature widget-2';

Comme indiqué précédemment, les zones de grille doivent être rectangulaires. Ça signifie que la variante suivante du dernier exemple n'est pas valable :

/* Invalid declaration */
grid-template-areas:
  'feature feature widget-1'
  'feature aside widget-2';

Nous pouvons créer des espaces (ou des "arrêts") entre les cellules

C'est possible en utilisant la notation point (.) :

grid-template-areas:
  "header header header"
  "sidebar main main"
  ". footer footer"; /* la 1ère cellule est vide */
}

Le nombre de points n'a pas d'importance. Nous aurions pu faire ceci à la place :

grid-template-areas:
  "header  header header"
  "sidebar main   main"
  "....... footer footer"; /* la 1ère cellule est vide */
}

Les deux déclarations créent la même grille :

La cellule de la première colonne, troisième rangée, est vide, effet de la notation point.

Les espaces blancs sont un bon moyen de visualiser la grille

Les déclarations suivantes sont équivalentes, mais la seconde permet de mieux visualiser la structure de la grille, car nous utilisons des espaces vides pour aligner les noms :

grid-template-areas:
  'header header header'
  'sidebar main main'
  '. footer footer';

grid-template-areas:
  'header  header header'
  'sidebar main   main'
  '.       footer footer';

Si vous cherchez une autre façon de visualiser un conteneur de grille, Chris a une idée astucieuse pour le "dessiner" dans une sorte de format ASCII.

Les rangées doivent avoir le même nombre de colonnes

Toutes les listes doivent avoir le même nombre de valeurs, sinon la déclaration n'est pas valide.

/* 👍 */
grid-template-areas:
  'name name-2 name-3'
  'name name-2 name-3'
  'name name-2 name-3';

/* 👍 */
grid-template-areas:
  'header header'
  '. main'
  'footer footer';

/* 👎 */
grid-template-areas:
  'name name-2 name-3'
  'name name-2 name-3'
  'name name-3';

Utilisation de caractères Unicode pour les zones de grille nommées

Selon les spécifications, tout nom qui ne correspond pas à la syntaxe ident doit être échappé lorsqu'il est fait référence à cette zone par son nom dans d'autres propriétés. Par exemple, dans la déclaration suivante, le nom de la première zone commence par un chiffre et ne correspond donc pas à la syntaxe <ident> :

.grid {
  grid-template-areas: '1st b c';
}

La solution consiste à déclarer le code hexadécimal non échappé pour le chiffre 1. Dans ce cas, c'est U+0031, que nous échappons dans le CSS sous la forme \31st. C'est donc ce que nous utilisons pour affecter un élément à la zone de grille nommée :

.grid-item {
  grid-area: \31st;
}

Noms de rangées attribués implicitement

La définition des pistes avec la propriété grid-template-areas nous donne gratuitement des noms de lignes basés sur les noms attribués. C'est différent des propriétés grid-template-rows et grid-template-columns où nous devons fournir des noms de lignes lors de la définition des colonnes et des rangées. Ce n'est pas le cas de la propriété grid-template-areas, car elle prend les noms que nous lui fournissons et produit des noms de pistes pour nous.

Quatre lignes de grille sont créées pour chaque nom de zone de grille. Si nous avons une zone de grille nommée sidebar, nous obtenons deux paires de lignes de piste nommées sidebar-start et sidebar-end - une paire pour la direction de la colonne et une paire pour la direction de la rangée :

Showing track lines in a CSS grid layout created with grid-template-areas.

On peut se demander ce qui se passe si l'on définit explicitement les noms des pistes et que l'on utilise le même nom que celui que l'on obtiendrait s'ils étaient définis implicitement — par exemple, si l'on définit explicitement une ligne de grille nommée sidebar-start pour une sidebar nommée area. Eh bien en fait les deux lignes peuvent coexister et être affectées à des éléments différents. En d'autres termes, la valeur explicite reste valable et les deux lignes peuvent être utilisées.

Zones nommées implicitement

Une autre façon de nommer les zones de grille dans un conteneur de grille est de laisser CSS Grid les nommer implicitement pour nous lors de la configuration des noms de pistes dans les propriétés grid-template-columns et grid-template-rows.

Tout ce que nous avons à faire est de choisir un nom pour la zone de grille et d'y ajouter à la fin -start et -end pour les noms de pistes. Ici, par exemple, nous obtenons une zone de grille appelée sidebar sans même déclarer la propriété grid-template-areas :

.grid-container {
  display: grid;
  grid-template-columns: [sidebar-start] 250px [sidebar-end] 1fr;
}

aside {
  grid-area: sidebar;
}

Comme le montre l'exemple ci-dessus, bien qu'il n'y ait pas de propriété grid-template-areas pour définir explicitement une zone nommée "sidebar", cette zone peut toujours être référencée par les propriétés grid-placement telles que grid-area, grid-row, grid-column ou leurs équivalents en écriture développée.

Exemple : Disposition réactive du Saint Graal

Dans la démo suivante, nous utilisons la propriété grid-template-areas pour créer la fameuse mise en page Holy Grail avec CSS Grid :

voir Holy grail layout with CSS Grid de Mojtaba Seyedi dans CodePen

Cette mise en page doit son nom au fait qu'elle était extrêmement difficile à réaliser à l'époque où l'on utilisait des float pour les mises en page. Heureusement, nous disposons de CSS Grid pour rendre cette tâche presque triviale.

Tout d'abord, notre HTML :

<div class="grid">
  <header>Header</header>
  <main>Main Content</main>
  <aside class="left-sidebar">Left Sidebar</aside>
  <aside class="right-sidebar">Right Sidebar</aside>
  <footer>Footer</footer>
</div>

C'est assez simple jusqu'à présent, pas vrai ? Nous voulons que l'en-tête soit en haut, que le pied de page soit en bas et que le contenu principal soit dans l'une des trois colonnes de la rangée du milieu.

Nous pouvons configurer les grid template areas nommées en CSS, et étendre les rangées si nécessaire :

.container {
  grid-template-columns: 12rem auto 12rem;
  grid-template-areas:
    'header header header'
    'left-sidebar main right-sidebar'
    'footer footer footer';
}

Nous devons maintenant assigner chaque élément à une zone de grille nommée :

header {
  grid-area: header;
}
main {
  grid-area: main;
}
footer {
  grid-area: footer;
}
.left-sidebar {
  grid-area: left-sidebar;
}
.right-sidebar {
  grid-area: right-sidebar;
}

Et voilà, techniquement c'est terminé ! C'est vraiment tout ce qu'il y a à faire. Nous pouvons aller plus loin en empilant les zones de la grille verticalement par défaut, puis construire le Saint Graal sur des écrans plus grands où l'aspect est bien meilleur :

.container {
  display: grid;
  grid-template-areas:
    /* Chaque zone est une rangée */
    'header'
    'nav'
    'article'
    'sidebar'
    'footer';
}

@media (min-width: 600px) {
  .container {
    grid-template-columns: 12rem auto 12rem;
    grid-template-areas:
      /* Build the Holy Grail layout */
      'header header header'
      'nav article article'
      'sidebar article article'
      'footer footer footer';
  }
}


Voir aussi dans La Cascade :

Autres ressources externes

Articles de Mojtaba Seyedi traduits dans La Cascade

Voir la page de Mojtaba Seyedi et la liste de ses articles dans La Cascade.
Article original paru le 26 mai 2022 dans CSS-Tricks
Traduit avec l'aimable autorisation de CSS-Tricks et de Mojtaba Seyedi.
Copyright CSS-Tricks © 2022