La Cascade

Rechercher

CSS Grid : grille implicite et placement automatique

par Temani Afif, 3 août 2022, cssgrid, css, article original paru le 1er août 2022 dans CSS Tricks

L'article le plus clair sur les grilles implicites et le placement automatique dans CSS Grid.


Lorsqu'on travaille avec CSS Grid, la première chose à faire est de définir display : grid sur l'élément (item) qui doit devenir un conteneur de grille. Ensuite, on définit explicitement la grille en utilisant une combinaison de grid-template-columns, grid-template-rows et grid-template-areas. Et à partir de là, l'étape suivante consiste à placer les éléments à l'intérieur de la grille.

C'est l'approche classique à utiliser et je la recommande également. Cependant, il existe une autre approche pour créer des grilles sans définition explicite. Nous l'appelons la grille implicite.

"Explicite, implicite ? Mais que se passe-t-il ici ?"

Des termes étranges, non ? Manuel Matuzovic a déjà donné une bonne explication de ce que nous entendons par "implicite" et "explicite" dans CSS Grid, mais allons directement à l'essentiel de ce que dit la spécification :

Les propriétés grid-template-rows, grid-template-columns et grid-template-areas définissent un nombre fixe de pistes qui forment la grille explicite. Lorsque les éléments de la grille sont positionnés en dehors de ces limites, le conteneur de grille génère des pistes de grille implicites en ajoutant des lignes de grille implicites à la grille. Ces lignes, associées à la grille explicite, forment la grille implicite.

En clair, le navigateur génère automatiquement des rangées et des colonnes supplémentaires si des éléments sont placés en dehors de la grille définie.

Qu'en est-il de l'auto-placement ?

Tout comme le concept de grille implicite, l'auto-placement est la capacité du navigateur à placer automatiquement les éléments à l'intérieur de la grille. Nous n'avons pas toujours besoin de donner la position de chaque élément.

A travers différents cas d'utilisation, nous allons voir comment ces fonctionnalités peuvent nous aider à créer des grilles complexes et dynamiques avec quelques lignes de code.

Barre latérale dynamique

voir implicit grid #1 de Temani Afif dans CodePen

Ici, nous avons trois mises en page différentes, mais nous n'avons qu'une seule configuration de grille qui fonctionne pour toutes.

main {
  display : grid ;
  grid-template-columns : 1fr ;
}

Une seule colonne occupe tout l'espace libre. Il s'agit de notre grille "explicite". Elle est configurée pour contenir un élément de la grille dans le conteneur principal de la grille. C'est tout. Une colonne et une rangée :

voir untitled de Geoff Graham dans CodePen

Mais que se passerait-il si nous décidions d'y déposer un autre élément, disons un aside (notre barre latérale dynamique). Telle qu'elle est actuellement (et explicitement) définie, notre grille devra s'ajuster automatiquement pour trouver un emplacement pour cet élément. Et si nous ne faisons rien d'autre avec notre CSS, voici ce que DevTools nous dit qu'il se passe.

L'élement 1 prend toute la colonne explicitement définie dans le container et le 2e se place sur une nouvelle rangée entre les lignes de grille implicites étiquetées 2 et 3. Notez que j'utilise un espace de 20px pour aider à séparer les choses visuellement.

Nous pouvons déplacer le <aside> vers une colonne à côté de la <section> :

aside {
  grid-column-start : 2 ;
}
voir untitled de Geoff Graham dans CodePen

Et voici ce que nous dit maintenant DevTools :

L'élément se trouve entre la première et la deuxième ligne de colonne de la grille. Il commence à la deuxième ligne de colonne de la grille et se termine à une troisième ligne que nous n'avons jamais déclarée.

Nous plaçons notre élément dans la deuxième colonne mais... attendez, nous n'avons pas de deuxième colonne ! C'est bizarre, non ? Nous n'avons jamais déclaré de deuxième colonne sur le conteneur de grille <main>, mais le navigateur en a créé une pour nous ! C'est la partie-clé de la spécification que nous avons examinée :

Lorsque les éléments de la grille sont positionnés en dehors de ces limites, le conteneur de grille génère des pistes de grille implicites en ajoutant des lignes de grille implicites à la grille.

Cette puissante fonctionnalité nous permet d'avoir des mises en page dynamiques. Si nous avons seulement l'élément <section>, tout ce que nous obtenons est une colonne. Mais si nous ajoutons un élément <aside> au mélange, une colonne supplémentaire est créée pour le contenir.

Nous pourrions placer l'élément <aside> avant l'élément <section> comme ceci :

aside {
  grid-column-end : -2 ;
}

Cela crée la colonne implicite au début de la grille, contrairement au code précédent qui plaçait la colonne implicite à la fin.

Nous pouvons avoir une sidebar à gauche ou à droite.

Nous pouvons faire la même chose plus facilement en utilisant la propriété grid-auto-flow pour définir que toutes les pistes implicites s'écoulent (flow) dans une direction column :

voir implicit grid #2 de Temani Afif dans CodePen

Maintenant, il n'est plus nécessaire de spécifier grid-column-start pour placer l'élément <aside> à droite de la <section> ! En fait, tout autre élément de la grille que nous décidons d'y jeter à tout moment s'écoulera désormais dans le sens de la colonne, chacun étant placé dans ses propres pistes de grille implicites. Parfait pour les situations où le nombre d'éléments de la grille n'est pas connu à l'avance !

Cela dit, nous avons toujours besoin de grid-column-end si nous voulons le placer dans une colonne à sa gauche car, sinon, le <aside> occupera la colonne explicite qui, à son tour, pousse la <section> en dehors de la grille explicite et l'oblige à prendre la colonne implicite.

Je sais, je sais. C'est un peu alambiqué. Voici un autre exemple que nous pouvons utiliser pour mieux comprendre cette petite bizarrerie :

voir with/without grid-column-end de Temani Afif dans CodePen

Dans le premier exemple, nous n'avons pas spécifié de placement. Dans ce cas, le navigateur placera d'abord l'élément <aside> dans la colonne explicite puisqu'il vient en premier dans le DOM. L'élément <section>, quant à lui, est automatiquement placé dans la colonne de grille que le navigateur crée automatiquement (ou implicitement) pour nous.

Dans le deuxième exemple, nous plaçons l'élément <aside> en dehors de la grille explicite :

aside {
  grid-column-end : -2 ;
}

Maintenant, il importe peu que <aside> vienne en premier dans le HTML. En réaffectant <aside> ailleurs, nous avons rendu l'élément <section> disponible pour prendre la colonne explicite.

Grille d'images

Essayons quelque chose de différent avec une grille d'images où nous avons une grande image et quelques vignettes à côté (ou en-dessous).

voir Big Image + thumbnails de Temani Afif dans CodePen

Nous avons deux configurations de grille. Mais devinez quoi ? Je ne définis aucune grille du tout, nada ! Tout ce que je fais, c'est ça :

.grid img:first-child {
  grid-area : span 3 / span 3 ;
}

Il est surprenant que nous n'ayons besoin que d'une seule ligne de code pour réaliser quelque chose comme ça, alors disséquons ce qui se passe et vous verrez que c'est plus facile que vous ne le pensez. Tout d'abord, grid-area est une propriété raccourcie qui combine les propriétés suivantes en une seule déclaration :

  • grid-row-start
  • grid-row-end
  • grid-column-start
  • grid-column-end

Attendez ! grid-area n'est-elle pas la propriété que nous utilisons pour définir des zones nommées au lieu de l'endroit où les éléments commencent et finissent sur la grille ?

Oui, mais elle fait plus. Nous pourrions écrire beaucoup de choses sur grid-area, mais dans ce cas particulier :

.grid img:first-child {
  grid-area : span 3 / span 3 ;
}

/* ...est équivalent à : */
.grid img:first-child {
  grid-row-start : span 3 ;
  grid-column-start : span 3 ;
  grid-row-end : auto ;
  grid-column-end : auto ;
}

Nous pouvons constater la même chose en ouvrant DevTools pour développer la version abrégée :

Cela signifie que le premier élément image de la grille doit couvrir trois colonnes et trois rangées. Mais comme nous n'avons pas défini de colonnes ou de rangées, le navigateur le fait pour nous.

Pour le dire simplement, nous avons placé la première image dans le HTML pour qu'elle occupe une grille de 3⨉3. Cela signifie que toutes les autres images seront placées automatiquement dans ces mêmes trois colonnes sans qu'il soit nécessaire de spécifier quoi que ce soit de nouveau.

En résumé, nous avons indiqué au navigateur que la première image devait occuper l'espace de trois colonnes et de trois rangées que nous n'avons jamais définies explicitement lors de la configuration du conteneur de grille. Le navigateur a défini ces colonnes et ces rangées pour nous. En conséquence, les autres images du HTML s'insèrent directement dans la grille en utilisant les mêmes trois colonnes et rangées. Et comme la première image occupe les trois colonnes de la première rangée, les autres images s'insèrent dans des rangées supplémentaires contenant chacune trois colonnes, où chaque image occupe une seule colonne.

Tout cela à partir d'une seule ligne de CSS ! C'est la puissance de la grille "implicite" et du placement automatique.

Pour la deuxième configuration de la grille dans cette démo, tout ce que j'ai fait est de changer la direction du flux automatique en utilisant grid-auto-flow : column de la même manière que nous l'avons fait précédemment en plaçant un élément <aside> à côté d'une <section>. Cela oblige le navigateur à créer une quatrième colonne qu'il peut utiliser pour placer les images restantes. Et puisque nous avons trois rangées, les images restantes sont placées à l'intérieur de la même colonne verticale.

Nous devons ajouter quelques propriétés aux images pour nous assurer qu'elles s'intègrent bien dans la grille sans débordement :

.grid {
  display : grid ;
  grid-gap : 10px ;
}

/* pour la deuxième configuration de la grille */
.horizontal {
  grid-auto-flow : column ;
}

/* La grande image 3⨉3 */
.grid img:first-child {
  grid-area : span 3 / span 3 ;
}

/* Aide à prévenir les images étirées ou déformées */
img {
  width : 100% ;
  hauteur : 100% ;
  object-fit : cover ;
}

Et bien sûr, nous pouvons facilement mettre à jour la grille pour prendre en compte plus d'images en ajustant une valeur. Il s'agit de la valeur 3 dans les styles pour la grande image. Nous avons ceci :

.grid img:first-child {
  grid-area : span 3 / span 3 ;
}

Mais nous pourrions ajouter une quatrième colonne en la remplaçant simplement par 4 :

.grid img:first-child {
  grid-area : span 4 / span 4 ;
}

Mieux encore : définissons cette propriété comme une propriété personnalisée pour faciliter encore plus la mise à jour.

voir Variable grid with thumbnail de Temani Afif dans CodePen

Mises en page dynamiques

Le premier cas d'utilisation avec la barre latérale était notre première mise en page dynamique. Nous allons maintenant nous attaquer à des mises en page plus complexes où le nombre d'éléments dictera la configuration de la grille.

voir Dynamic layout #1 de Temani Afif dans CodePen

Dans cet exemple, nous pouvons avoir de un à quatre éléments et la grille s'ajuste de manière à s'adapter au nombre d'éléments sans laisser de vides ou d'espaces manquants.

Lorsque nous n'avons qu'un seul élément, nous ne faisons rien. L'élément s'étire pour remplir la seule rangée et la seule colonne créées automatiquement par la grille.

Mais lorsque nous ajoutons le deuxième élément, nous créons une autre colonne (implicite) en utilisant grid-column-start : 2.

Lorsque nous ajoutons un troisième élément, il doit occuper la largeur de deux colonnes — c'est pourquoi nous avons utilisé grid-column-start : span 2, mais seulement s'il s'agit du :last-child car si nous ajoutons un quatrième élément, celui-ci ne doit occuper qu'une seule colonne.

En additionnant tout cela, nous avons quatre configurations de grille avec seulement deux déclarations et la magie de la grille implicite :

.grid {
  display : grid ;
}
.grid :nth-child(2) {
  grid-column-start : 2 ;
}
.grid :nth-child(3):last-child {
  grid-column-start : span 2 ;
}

Essayons-en un autre :

voir Dynamic layout #2 de Temani Afif dans CodePen

Nous ne faisons rien pour les premier et deuxième cas où nous n'avons qu'un ou deux éléments. En revanche, lorsque nous ajoutons un troisième élément, nous indiquons au navigateur que, tant qu'il s'agit du :last-child, il doit s'étendre sur deux colonnes. Lorsque nous ajoutons un quatrième élément, nous indiquons au navigateur que cet élément doit être placé dans la deuxième colonne.

.grid {
  display : grid ;
}
.grid :nth-child(3):last-child {
  grid-column-start : span 2 ;
}
.grid :nth-child(4) {
  grid-column-start : 2 ;
}

Vous commencez à comprendre le truc ? Nous donnons au navigateur des instructions spécifiques basées sur le nombre d'éléments (en utilisant :nth-child) et, parfois, une seule instruction peut changer complètement la mise en page.

Il convient de noter que le dimensionnement ne sera pas le même lorsque nous travaillons avec des contenus différents :

voir Different content de Temani Afif dans CodePen

Comme nous n'avons pas défini de taille pour nos éléments, le navigateur les dimensionne automatiquement pour nous en fonction de leur contenu et nous pouvons nous retrouver avec une taille différente de celle que nous venons de voir. Pour y remédier, nous devons spécifier explicitement que toutes les colonnes et les rangées ont la même taille :

grid-auto-rows : 1fr ;
grid-auto-columns : 1fr ;

Hé, nous n'avons pas encore joué avec ces propriétés ! grid-auto-rows et grid-auto-columns définissent la taille des rangées et des colonnes implicites, respectivement, dans un conteneur de grille. Ou, comme l'explique la spécification :

Les propriétés grid-auto-columns et grid-auto-rows spécifient la taille des pistes auxquelles une taille n'est pas attribuée par grid-template-rows ou grid-template-columns.

voir Same size items de Temani Afif dans CodePen

Voici un autre exemple où nous pouvons aller jusqu'à six éléments. Cette fois, je vais vous laisser disséquer le code. Ne vous inquiétez pas, les sélecteurs peuvent sembler complexes mais la logique est assez simple.

voir Dynamic layout #3 de Temani Afif dans CodePen

Même avec six éléments, nous n'avons eu besoin que de deux déclarations. Imaginez toutes les mises en page complexes et dynamiques que nous pouvons réaliser avec quelques lignes de code !

Que se passe-t-il avec ce grid-auto-rows et pourquoi prend-il trois valeurs ? Sommes-nous en train de définir trois rangées ?

Non, nous ne définissons pas trois rangées. Mais nous définissons de fait trois valeurs comme modèle pour nos rangées implicites. La logique est la suivante :

  • Si nous avons une rangée, elle sera dimensionnée avec la première valeur.
  • Si nous avons deux rangées, la première reçoit la première valeur et la seconde la seconde.
  • Si nous avons trois rangées, les trois valeurs seront utilisées.
  • Si nous avons quatre rangées (et voici la partie intéressante), nous utilisons les trois valeurs pour les trois premières rangées et nous réutilisons la première valeur pour la quatrième rangée. C'est pourquoi il s'agit d'une sorte de modèle que nous répétons pour dimensionner toutes les rangées implicites.
  • Si nous avons 100 rangées, elles seront dimensionnées trois par trois pour avoir 2fr 2fr 1fr 2fr 2fr 1fr 2fr 2fr 1fr, etc.

Contrairement à grid-template-rows qui définit le nombre de rangées et leur taille, grid-auto-rows ne dimensionne que les rangées qui peuvent être créées en cours de route.

Si nous revenons à notre exemple, la logique est d'avoir une taille égale lorsque deux rangées sont créées (nous utiliserons le 2fr 2fr), mais si une troisième rangée est créée, nous la rendons un peu plus petite.

Motifs de grille

Pour ce dernier point, nous allons parler de motifs. Vous avez probablement vu ces mises en page à deux colonnes où une colonne est plus large que l'autre, et où chaque rangée alterne le placement de ces colonnes.

Ce type de disposition peut être difficile à réaliser sans connaître exactement la quantité de contenu à traiter, mais les pouvoirs implicites de placement automatique de CSS Grid en font un jeu d'enfant.

voir Alternate CSS grid de Temani Afif dans CodePen

Jetez un coup d'œil au code. Il peut sembler complexe, mais décomposons-le car il est finalement assez simple.

La première chose à faire est d'identifier le modèle. Demandez-vous : "Après combien d'éléments le modèle doit-il se répéter ?" Dans ce cas, c'est tous les quatre éléments. Donc, pour l'instant, n'utilisons que quatre éléments :

Maintenant, définissons la grille et mettons en place le modèle général en utilisant le sélecteur :nth-child pour alterner entre les éléments :

.grid {
  display : grid ;
  grid-auto-columns : 1fr ; /* toutes les colonnes sont égales */
  grid-auto-rows : 100px ; /* toutes les rangées sont égales à 100px */
}
.grid :nth-child(4n + 1) { /* ? ?? */ }
.grid :nth-child(4n + 2) { /* ? ?? */ }
.grid :nth-child(4n + 3) { /* ? ?? */ }
.grid :nth-child(4n + 4) { /* ? ?? */ }

Nous avons dit que notre motif se répète tous les quatre éléments, nous utiliserons donc logiquement 4n + x où x va de 1 à 4. Il est un peu plus facile d'expliquer le motif de cette façon :

4(0) + 1 = 1 = 1er élément /* on commence avec n = 0 */
4(0) + 2 = 2 = 2ème élément
4(0) + 3 = 3 = 3ème élément
4(0) + 4 = 4 = 4e élément
4(1) + 1 = 5 = 5ème élément /* notre modèle se répète ici à n = 1 */
4(1) + 2 = 6 = 6ème élément
4(1) + 3 = 7 = 7ème élément
4(1) + 4 = 8 = 8e élément
4(2) + 1 = 9 = 9ème élément /* notre modèle se répète ici à n = 2 */
etc.

C'est parfait, non ? Nous avons quatre éléments, et nous répétons le motif sur le cinquième élément, le neuvième élément et ainsi de suite.

Ces sélecteurs :nth-child peuvent être délicats ! Chris a expliqué de manière très utile comment tout cela fonctionne, y compris des recettes pour créer différents modèles.

Maintenant, nous configurons chaque élément de la manière suivante :

  1. Le premier élément doit prendre deux colonnes et commencer à la première colonne (grid-column : 1/span 2).
  2. Le deuxième élément est placé dans la troisième colonne (grid-column-start : 3).
  3. Le troisième élément est placé à la première colonne : (grid-column-start : 1).
  4. Le quatrième élément prend deux colonnes et commence à la deuxième colonne : (grid-column : 2/span 2).

Voici ce que cela donne en CSS :

.grid {
  display : grid ;
  grid-auto-columns : 1fr ; /* toutes les colonnes sont égales */
  grid-auto-rows : 100px ; /* toutes les rangées sont égales à 100px */
}
.grid :nth-child(4n + 1) { grid-column : 1/span 2 ; }
.grid :nth-child(4n + 2) { grid-column-start : 3 ; }
.grid :nth-child(4n + 3) { grid-column-start : 1 ; }
.grid :nth-child(4n + 4) { grid-column : 2/span 2 ; }

Nous pourrions nous arrêter ici et ce serait bon... mais nous pouvons faire mieux ! Plus précisément, nous pouvons supprimer certaines déclarations et compter sur les pouvoirs de placement automatique de la grille pour faire le travail à notre place. C'est la partie la plus délicate à appréhender et il faut beaucoup de pratique pour pouvoir identifier ce qui peut être supprimé.

La première chose que nous pouvons faire est de mettre à jour grid-column : 1 /span 2 et d'utiliser uniquement grid-column : span 2 puisque, par défaut, le navigateur placera le premier élément dans la première colonne. Nous pouvons également supprimer cet élément :

.grid :nth-child(4n + 3) { grid-column-start : 1 ; }

En plaçant les premier, deuxième et quatrième éléments, la grille place automatiquement le troisième élément au bon endroit. Cela signifie que nous nous retrouvons avec ceci :

.grid {
  display : grid ;
  grid-auto-rows : 100px ; /* toutes les rangées sont égales à 100px */
  grid-auto-columns : 1fr ; /* toutes les colonnes sont égales */
}
.grid :nth-child(4n + 1) { grid-column : span 2 ; }
.grid :nth-child(4n + 2) { grid-column-start : 3 ; }
.grid :nth-child(4n + 4) { grid-column : 2/span 2 ; }

Mais allez, on peut faire mieux ! Nous pouvons aussi supprimer ceci :

.grid :nth-child(4n + 2) { grid-column-start : 3 ; }

Pourquoi ? Si nous plaçons le quatrième élément dans la deuxième colonne tout en lui permettant d'occuper deux colonnes complètes, nous forçons la grille à créer une troisième colonne implicite, ce qui nous donne un total de trois colonnes sans le lui dire explicitement. Le quatrième élément ne peut pas aller dans la première rangée puisque le premier élément prend également deux colonnes, il passe donc à la rangée suivante. Cette configuration nous laisse avec une colonne vide dans la première rangée et une colonne vide dans la deuxième rangée.

Je pense que vous connaissez la fin de l'histoire. Le navigateur placera automatiquement les deuxième et troisième éléments dans ces emplacements vides. Notre code devient donc encore plus simple :

.grid {
  display : grid ;
  grid-auto-columns : 1fr ; /* toutes les colonnes sont égales */
  grid-auto-rows : 100px ; /* toutes les rangées sont égales à 100px */
}
.grid :nth-child(4n + 1) { grid-column : span 2 ; }
.grid :nth-child(4n + 4) { grid-column : 2/span 2 ; }

Il suffit de cinq déclarations pour créer un motif très cool et très souple. La partie optimisation peut être délicate, mais on s'y habitue et on gagne quelques astuces avec la pratique.

Pourquoi ne pas utiliser grid-template-columns pour définir des colonnes explicites puisque nous connaissons le nombre de colonnes ?

Nous pouvons le faire ! Voici le code correspondant :

.grid {
  display : grid ;
  grid-template-columns : repeat(3, 1fr) ; /* toutes les colonnes sont égales */
  grid-auto-rows : 100px ; /* toutes les rangées sont égales à 100px */
}
.grid :nth-child(4n + 1),
.grid :nth-child(4n + 4) {
  grid-column : span 2 ;
}
voir Another alternative de Temani Afif dans CodePen

Comme vous pouvez le constater, le code est nettement plus intuitif. Nous définissons trois colonnes de grille explicites et nous indiquons au navigateur que les premier et quatrième éléments doivent prendre deux colonnes. Je recommande vivement cette approche ! Mais le but de cet article est d'explorer de nouvelles idées et astuces que nous obtenons grâce aux pouvoirs implicites et d'auto-placement de CSS Grid.

L'approche explicite est plus directe, tandis qu'une grille implicite vous oblige à combler les lacunes là où CSS effectue un travail supplémentaire en coulisse. En fin de compte, je pense qu'une bonne compréhension des grilles implicites vous aidera à mieux comprendre l'algorithme CSS Grid. Après tout, nous ne sommes pas ici pour étudier ce qui est évident — nous sommes ici pour explorer des territoires sauvages !

Essayons un autre modèle, un peu plus rapide cette fois :

voir Alternate CSS grid de Temani Afif dans CodePen

Notre schéma se répète tous les six éléments. Les troisième et quatrième éléments doivent occuper chacun deux rangées complètes. Si nous plaçons le troisième et le quatrième éléments, il semble que nous n'ayons pas besoin de toucher aux autres, alors essayons ce qui suit :

.grid {
  display : grid ;
  grid-auto-columns : 1fr ;
  grid-auto-rows : 100px ;
}
.grid :nth-child(6n + 3) {
  grid-area : span 2/2 ; /* grid-row-start : span 2 && grid-column-start : 2 */
}
.grid :nth-child(6n + 4) {
  grid-area : span 2/1 ; /* grid-row-start : span 2 && grid-column-start : 1 */
}
voir Premier essai de Temani Afif dans CodePen

Hmm, pas terrible. Nous devons placer le deuxième élément dans la première colonne. Sinon, la grille le placera automatiquement dans la deuxième colonne.

.grid :nth-child(6n + 2) {
  grid-column : 1 ; /* grid-column-start : 1 */
}
voir Deuxième essai de Temani Afif dans CodePen

C'est mieux, mais il y a encore du boulot. Nous devons déplacer le troisième élément vers le haut. Il est tentant d'essayer de le placer dans la première rangée de cette façon :

.grid :nth-child(6n + 3) {
  grid-area : 1/2/span 2 ; 
    /* Équivalent à :
       grid-row-start : 1 ;
       grid-row-end : span 2 ;
       grid-column-start : 2 
     */
}

Mais cela ne fonctionne pas car cela oblige tous les 6n + 3 éléments à être placés dans la même zone, ce qui donne une disposition désordonnée. La véritable solution consiste à conserver la définition initiale du troisième élément et à ajouter grid-auto-flow : dense pour combler les vides. Extrait du MDN en français :

L'algorithme de placement automatique utilisera une méthode de « regroupement dense » où il essaie de remplir les trous dans la grille si des éléments plus petits arrivent ensuite. De fait, on peut obtenir une impression de désordre alors qu'il s'agit simplement du comblement des espaces libres.
Si cette valeur est absente, le moteur utilisera un algorithme simple qui ne fait que se déplacer vers l'avant, sans revenir vers les espaces vides. De cette façon, les éléments apparaitront nécessairement dans l'ordre mais pourront laisser des trous.

Je sais que cette propriété n'est pas très intuitive mais ne l'oubliez jamais lorsque vous êtes confronté à un problème de placement. Avant d'essayer en vain différentes configurations, ajoutez-la, car elle peut réparer votre mise en page sans effort supplémentaire.

Pourquoi ne pas toujours ajouter cette propriété par défaut ?

Je ne le recommande pas car, dans certains cas, nous ne voulons pas de ce comportement. Notez que l'explication de MDN mentionne que cela entraîne la circulation d'éléments "en désordre" pour remplir les trous laissés par des éléments plus grands. L'ordre visuel est généralement tout aussi important que l'ordre des sources, en particulier lorsqu'il s'agit d'interfaces accessibles, et grid-auto-flow : dense peut parfois provoquer un décalage entre l'ordre visuel et l'ordre des sources.

Notre code final est donc :

.grid {
  display : grid ;
  grid-auto-columns : 1fr ;
  grid-auto-flow : dense ;
  grid-autorows : 100px ;
}
.grid :nth-child(6n + 2) { grid-column : 1 ; }
.grid :nth-child(6n + 3) { grid-area : span 2/2 ; }
.grid :nth-child(6n + 4) { grid-row : span 2 ; }

Encore un petit ? Allez on y va !

voir Alternating row CSS Grid de Temani Afif dans CodePen

Pour celui-ci, je ne vais pas trop parler et plutôt vous montrer une illustration du code que j'ai utilisé. Essayez de voir si vous comprenez comment j'ai obtenu ce code :

Les éléments en noir sont implicitement placés dans la grille. Il faut noter que l'on peut obtenir la même disposition de plusieurs manières différentes. Pouvez-vous aussi les comprendre ? Qu'en est-il de l'utilisation de grid-template-columns ?

Je vais vous laisser avec un dernier modèle :

J'ai une solution pour celui-ci mais c'est à vous de vous entraîner. Prenez tout ce que nous avons appris et essayez de le coder vous-même, puis comparez-le avec ma solution. Ne vous inquiétez pas si vous terminez par quelque chose de verbeux - le plus important est de trouver une solution qui fonctionne.

Vous en voulez encore ?

Avant de terminer, je voudrais partager avec vous quelques questions de Stack Overflow liées à CSS Grid, auxquelles j'ai répondu en utilisant plusieurs des techniques que nous avons abordées ici. C'est une bonne liste qui montre combien de cas d'utilisation réels et de situations concrètes se présentent où ces choses sont utiles :

Pour conclure

CSS Grid existe depuis des années, mais il existe encore de nombreuses astuces peu connues et utilisées qui ne sont pas largement discutées. La grille implicite et les fonctions de placement automatique sont deux d'entre elles !

Et oui, cela peut devenir un défi ! Il m'a fallu beaucoup de temps pour comprendre la logique des grilles implicites et j'ai encore du mal avec le placement automatique. Si vous voulez passer plus de temps à vous faire une idée des grilles explicites et implicites, voici quelques explications et exemples supplémentaires qui valent la peine d'être consultés :

Voir la liste des articles de Temani Afif traduits dans La Cascade.
Article original paru le 1er août 2022 dans CSS Tricks
Traduit avec l'aimable autorisation de CSS Tricks et de Temani Afif.
Copyright CSS Tricks © 2022