// css · Web Platform Advent #16
Subgrid CSS : faire partager au sous-grille les lignes du parent
Une grille imbriquée invente ses propres pistes, donc les cartes voisines ne s'alignent jamais. Subgrid fait adopter à l'enfant les lignes de son parent : ce que ça règle, les deux règles à retenir, et la différence avec display: contents.
Subgrid règle une frustration précise, et il vaut mieux l'énoncer exactement parce que tout le reste en découle : une grille imbriquée crée ses propres pistes, qui n'ont aucun rapport avec celles du parent. Trois cartes côte à côte, chacune disposant son titre, son corps et son pied en grille interne, dimensionneront donc ces lignes indépendamment - et les pieds ne s'aligneront pas.
Subgrid dit à l'enfant d'arrêter d'inventer des pistes et d'utiliser les lignes du parent.
Le problème, concrètement
Voici la mise en page que tout le monde rencontre. Une grille extérieure de cartes, et chaque carte est elle-même une grille de trois lignes :
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1rem;
}
.card {
display: grid;
grid-template-rows: auto 1fr auto;
} Chaque carte dimensionne maintenant ses trois lignes à partir de son propre contenu. Une carte au titre sur deux lignes obtient une première ligne plus haute que sa voisine au titre sur une seule. Résultat : trois cartes dont les éléments internes sont tous légèrement décalés - et aucun style appliqué dans la carte n'y changera rien, puisque chaque carte mesure isolément.
La correction, et les deux règles
Faites de la carte une subgrid sur l'axe que vous voulez aligner :
.cards {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: auto 1fr auto;
gap: 1rem;
}
.card {
display: grid;
grid-row: span 3;
grid-template-rows: subgrid;
} Désormais les trois lignes de chaque carte sont les trois lignes du parent. Le titre le plus haut de la série définit la ligne 1 pour toutes, si bien que titres, corps et pieds tombent sur les mêmes lignes d'un bout à l'autre de la rangée.
Deux règles méritent d'être retenues, parce que la quasi-totalité des « subgrid ne marche pas » se ramène à l'une des deux :
- L'élément doit être un enfant direct de la grille dont il reprend les pistes. Subgrid ne traverse pas un wrapper : glissez un
<div>ordinaire entre la grille parente et la carte, et la relation est rompue. - Il n'adopte que les pistes qu'il enjambe. Une carte qui enjambe trois lignes en adopte trois. Sans déclaration de span, elle en enjambe une, et vous obtenez une seule piste - ce qui ressemble exactement à un subgrid sans effet.
Ça fonctionne axe par axe
On applique subgrid aux lignes et aux colonnes indépendamment. Un enfant peut reprendre les colonnes du parent tout en définissant ses propres lignes, cas très courant :
.child {
display: grid;
grid-column: span 4;
grid-template-columns: subgrid; /* colonnes du parent */
grid-template-rows: auto auto; /* ses propres lignes */
} C'est ainsi qu'on aligne un bloc imbriqué sur un système de colonnes valable pour toute la page sans renoncer au contrôle de son rythme vertical.
Gouttières et lignes nommées suivent
Deux commodités faciles à manquer :
- La gouttière est héritée du parent sur l'axe subgridé, ce qui est en général le comportement souhaité. Déclarez
gapsur l'enfant pour la surcharger. - Les lignes nommées sont héritées aussi : si le parent définit
[content-start]et[content-end], l'enfant peut placer ses éléments directement sur ces noms.
Subgrid contre display: contents
Avant subgrid, le contournement habituel était display: contents sur le wrapper, qui supprime sa boîte et promeut ses enfants au rang d'éléments de la grille extérieure. Ça aligne, et ça coûte la boîte : plus de fond, plus de bordure, plus de padding, plus de border-radius sur la carte, puisque la carte ne génère plus de boîte où les peindre.
display: contents | subgrid | |
|---|---|---|
| Alignement entre voisins | Oui | Oui |
| Conserve la boîte du wrapper | Non | Oui |
| Fond, bordure, padding | Perdus | Conservés |
| Contrôle par axe | Non | Oui |
Si la carte doit ressembler à une carte, subgrid est la réponse, et display: contents ne l'a jamais été.
Support navigateurs
Firefox a livré subgrid le premier, dès 2019, et est resté plusieurs années le seul moteur à le proposer. Safari l'a ajouté en 2022 et Chrome en 2023 : c'est donc disponible dans les versions actuelles de tous les grands navigateurs - assez récent pour qu'il vaille mieux vérifier votre propre cible de support que de le supposer.
Le modèle mental est simple une fois saisi : une grille imbriquée ordinaire demande « de combien de place je dispose, et comment la découper ? ». Une subgrid demande « où sont les lignes de mon parent ? » - et c'est cette seconde question qui fait qu'une rangée de cartes paraît dessinée plutôt que simplement posée. Si le choix du mécanisme de mise en page n'est pas encore tranché, commencez par CSS Grid contre Flexbox ; et pour des composants qui doivent s'adapter à la place qu'on leur donne plutôt qu'à l'écran, associez ceci aux container queries.