Stylisation des cellules vides avec le contenu généré et la mise en page de la grille CSS
Publié: 2022-03-10Un piège courant de la mise en page de la grille est lorsqu'un nouveau venu dans la méthode de mise en page se demande comment styliser une cellule de la grille qui ne contient aucun contenu. Dans la spécification de niveau 1 actuelle, cela n'est pas possible car il n'y a aucun moyen de cibler une cellule de grille ou une zone de grille vide et d'appliquer un style. Cela signifie que pour appliquer un style, vous devez insérer un élément.
Dans cet article, je vais voir comment utiliser CSS Generated Content pour obtenir un style de cellules vides sans ajouter d'éléments vides redondants et montrer quelques cas d'utilisation où cette technique a du sens.
Regardons de plus près BFC
Si vous avez déjà créé une mise en page avec CSS, vous savez probablement ce qu'est BFC. Comprendre pourquoi cela fonctionne et comment en créer un est utile et peut vous aider à comprendre le fonctionnement de la mise en page en CSS. Lire un article connexe →
Pourquoi ne pouvons-nous pas déjà styliser les zones vides ?
Le paragraphe d'ouverture de la spécification de grille indique :
« Ce module CSS définit un système de mise en page basé sur une grille en deux dimensions, optimisé pour la conception d'interface utilisateur. Dans le modèle de mise en page en grille, les enfants d'un conteneur de grille peuvent être positionnés dans des emplacements arbitraires dans une grille de mise en page flexible ou de taille fixe prédéfinie.
La phrase clé ici est "les enfants d'un conteneur de grille". La spécification définit la création d'une grille sur l'élément parent, dans laquelle les éléments enfants peuvent être positionnés. Il ne définit aucun style de cette grille, n'allant même pas jusqu'à implémenter quelque chose comme la propriété column-rule
que nous avons dans Multi-column Layout. Nous stylisons les éléments enfants, et non la grille elle-même, ce qui nous oblige à avoir un élément quelconque auquel appliquer ce style.
Utilisation d'éléments redondants comme crochet de style
Une façon d'insérer quelque chose dans le style consiste à insérer un élément redondant dans le document, par exemple, un span ou un div. Les développeurs ont tendance à ne pas aimer cette idée, malgré le fait qu'ils ajoutent depuis des années des "emballages de lignes" supplémentaires redondants afin d'obtenir des dispositions de grille à l'aide de flottants. Peut-être que cet élément évidemment vide est plus désagréable que la redondance quelque peu cachée de l'élément d'emballage !
Les éléments complètement vides deviennent des éléments de grille et peuvent avoir des arrière-plans et des bordures ajoutés, tout comme un élément qui contient du contenu, comme le montre cet exemple.
Voir les éléments Pen Empty devenir Grid Items par Rachel Andrew (@rachelandrew) sur CodePen.
Eric Meyer, dans son article A List Apart Faux Grid Tracks, préconise l'utilisation de l'élément b
comme élément redondant de choix, car il ne confère aucune signification sémantique, est court et également assez évident dans le balisage comme un crochet.
Il est peu probable que l'insertion de quelques éléments div
ou b
supplémentaires soit le plus grand crime contre un bon balisage que vous ayez jamais commis, donc je ne perdrais pas de sommeil en choisissant cette approche si nécessaire. Le développement Web implique très souvent de choisir l'approche la moins sous-optimale pour faire le travail jusqu'à ce qu'une meilleure solution soit conçue. Je préfère cependant garder mon style au même endroit si possible, en toute sécurité dans la feuille de style. Au moins, cela facilite la réutilisation des styles, sans avoir à se soucier du balisage supplémentaire requis. C'est pour cette raison que j'ai tendance à me tourner vers le contenu généré, quelque chose que je connais très bien grâce au travail que j'ai effectué sur le formatage de livres avec CSS, où vous passez la plupart de votre temps à travailler avec cette fonctionnalité.
Utilisation du contenu généré comme crochet de style
CSS Generated Content utilise les pseudo-classes CSS ::before
et ::after
ainsi que la propriété content
pour insérer une sorte de contenu dans le document. L'idée d'insérer du contenu pourrait vous amener à penser qu'il s'agit d'insérer du texte, et bien que cela soit possible, pour nos besoins, nous sommes intéressés par l'insertion d'un élément vide en tant qu'enfant direct de notre Grid Container. Avec un élément inséré, nous pouvons le styliser.
Dans l'exemple ci-dessous, j'ai un élément contenant, qui deviendra mon Grid Container, avec un autre élément imbriqué à l'intérieur. Cet enfant direct unique deviendra un élément de grille. J'ai défini une grille à trois colonnes et trois rangées sur le conteneur, puis positionné l'élément unique à l'aide de lignes de grille, de sorte qu'il se trouve dans la cellule de grille du milieu.
<div class="grid"> <div class="item"></div> </div>
.grid { display: grid; grid-template-columns: 100px 100px 100px; grid-template-rows: 100px 100px 100px; grid-gap: 10px; } .grid > * { border: 2px solid rgb(137,153,175); } .item { grid-column: 2; grid-row: 2; }
Si nous jetons un coup d'œil à cet exemple, en utilisant l'inspecteur de grille de Firefox pour superposer les lignes de la grille, nous pouvons voir comment les autres cellules vides de la grille existent, cependant, pour leur ajouter un arrière-plan ou une bordure, nous aurions besoin d'ajouter un enfant supplémentaire. éléments. C'est exactement ce que permet le contenu généré.

Dans mon CSS, j'ajoute une chaîne vide, ::before
et ::after
mon Grid Container. Ceux-ci deviendront immédiatement des éléments de grille et s'étireront pour remplir leur conteneur. J'ajoute ensuite le style dont j'ai besoin pour les boîtes, dans ce cas en ajoutant une couleur d'arrière-plan, et je les positionne comme je le ferais avec n'importe quel élément de grille ordinaire.
.grid::before { content: ""; background-color: rgb(214,232,182); grid-column: 3; grid-row: 1; } .grid::after { content: ""; background-color: rgb(214,232,182); grid-column: 1; grid-row: 3; }

Dans le document, nous n'avons toujours qu'un seul élément enfant, les éléments de style redondants sont contenus dans le CSS, ce qui semble parfaitement raisonnable car ils ne sont là qu'à des fins de style.
Limites de l'approche du contenu généré
Le problème évident avec cette approche deviendra évident si vous décidez que vous souhaitez également styliser les cellules de grille en haut à droite et en bas à gauche. Vous ne pouvez appliquer qu'un élément de contenu généré en haut et un en bas du conteneur, plusieurs pseudo-éléments ::before
et ::after
ne sont pas autorisés. La méthode ne fonctionnera pas si vous voulez créer vous-même un damier CSS Grid ! Si vous trouvez que vous avez besoin de faire beaucoup de style de cellules vides, alors dans un avenir prévisible, l'approche "Filler B" expliquée ci-dessus sera probablement votre meilleur pari.
La méthode du contenu généré pourrait également dérouter un futur développeur travaillant sur votre projet. Comme nous ciblons le conteneur, si vous réutilisez cette classe ailleurs, elle apportera le contenu généré, c'est utile si c'est ce que vous voulez. Dans l'exemple suivant, nous avons ajouté des lignes décoratives de chaque côté d'un titre, il serait raisonnable que chaque instance d'un h1
ait ces lignes. Cependant, ce serait très déroutant si vous ne saviez pas que cela allait se produire ! Une ligne de commentaire au-dessus des règles du conteneur vous aidera ici. J'ai tendance à travailler ces jours-ci dans une bibliothèque de modèles, ce qui aide vraiment à regrouper ces composants en un seul endroit, ce qui rend plus évident ce qui se passe lorsqu'une classe est appliquée à un élément.
Titres fantaisie
L'une de mes astuces préférées pour le contenu généré consiste à styliser les titres. Dans le passé, je devais repousser les styles de titre qui nécessitaient des emballages supplémentaires et des pistes de positionnement absolu à réaliser. Lorsque le contenu provient d'un CMS, il est souvent impossible d'ajouter ces wrappers redondants.
Avec la grille et le contenu généré, nous pouvons ajouter une ligne de chaque côté de notre en-tête sans ajouter de balisage supplémentaire. La ligne grandira et rétrécira en fonction de l'espace disponible et reviendra élégamment à un en-tête simple centré lorsque Grid n'est pas disponible dans les navigateurs.


Notre balisage est un simple h1
.
<h1>My heading</h1>
Dans les règles pour le h1
, je crée une grille à trois colonnes. La valeur de grid-template-columns
donne une piste de 1fr
puis une de auto
et une piste finale de 1fr
. Les deux pistes 1fr
partageront l'espace disponible restant après que le cap aura pris l'espace dont il a besoin pour être assis à l'intérieur de la piste de taille auto
.
J'ai ajouté la propriété text-align
avec une valeur de center
afin que mon en-tête soit saisi dans les navigateurs sans grille.
h1 { text-align: center; display: grid; grid-template-columns: 1fr auto 1fr; grid-gap: 20px; }
Nous ajoutons maintenant notre contenu généré, pour ajouter une ligne avant et après le texte du titre. J'enveloppe ces règles dans une requête de fonctionnalité, afin que nous n'obtenions aucun contenu généré bizarre dans les navigateurs sans disposition de grille.
La ligne elle-même est une bordure sur l'élément généré.
@supports (display: grid) { h1:before, h1:after { content: ""; align-self: center; border-top: 1px solid #999; } }
C'est tout ce que vous devez faire ! Vous pouvez utiliser la même technique pour ajouter n'importe quel style, ou même une icône des deux côtés d'un élément, au-dessus ou en dessous de l'élément. En plaçant votre élément dans une piste séparée, vous savez qu'il n'y a aucune chance que l'élément finisse par chevaucher votre texte d'en-tête, ce qui a tendance à être le problème lorsque vous essayez de faire ce genre de chose avec un positionnement absolu. Vous bénéficiez également de la manière précise dont les éléments peuvent être alignés les uns par rapport aux autres dans la grille.
Voir l'exemple d'en-tête Pen Generated Content de Rachel Andrew (@rachelandrew) sur CodePen.
Il s'agit d'un bel exemple d'amélioration possible à l'aide de la disposition en grille dont vous pourriez profiter même si vous n'êtes pas encore prêt à vous lancer dans une refonte majeure à l'aide de la grille. Il revient très bien à un titre simple, les personnes disposant de navigateurs compatibles obtiennent la touche supplémentaire et tout le monde obtient le contenu. Une approche similaire a été adoptée par Eric Meyer, utilisant le contenu généré pour ajouter des citations facilement stylisées et positionnables à un élément blockquote.
Avec ces petites fonctionnalités, je ne commence souvent pas à penser que je vais utiliser Grid Layout. C'est au fur et à mesure que je commence à comprendre comment mettre en œuvre ma conception que je réalise que c'est la méthode de mise en page à choisir. C'est pour cette raison que j'encourage les gens à ne pas considérer Grid comme une mise en page sur des composants, si vous le faites, vous risquez de manquer de nombreuses opportunités où cela peut aider.
Ajout d'arrière-plans et de bordures aux zones de votre conception
Nous pouvons également utiliser le contenu généré pour empiler les éléments ; le fait est que plusieurs éléments peuvent occuper une cellule de grille particulière. Cela peut inclure les éléments insérés avec le contenu généré.
Dans l'exemple suivant, j'ai une conception avec deux sections de contenu et un élément pleine largeur. Derrière le contenu se trouve un arrière-plan qui s'exécute également sous l'élément pleine largeur.

Le balisage a un conteneur avec les sections et l'élément pleine largeur comme enfants directs, et j'utilise le placement basé sur les lignes pour placer mes éléments sur la grille.
<article class="grid"> <section class="section1"> <p>…</p> </section> <div class="full-width"> <img src=“placeholder.jpg” alt=“Placeholder”> </div> <section class="section2"> <p>…</p> </section> </article>
.grid { display: grid; grid-template-columns: 1fr 20px 4fr 20px 1fr; grid-template-rows: auto 300px auto; grid-row-gap: 1em; } .section1 { grid-column: 3; grid-row: 1; } .section2 { grid-column: 3; grid-row: 3; } .full-width { grid-column: 1 / -1; grid-row: 2; background-color: rgba(214,232,182,.5); padding: 20px 0; }
Cela me donne la mise en page avec l'image pleine largeur et deux sections de contenu placées ; cependant, si j'ajoute l'arrière-plan aux sections, il s'arrêtera au-dessus de l' row-gap
entre la section
et l'image pleine largeur.
.section { background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }

Si nous supprimions le grid-row-gap
et utilisions le rembourrage pour créer l'espace, cela n'activerait toujours pas l'effet de l'arrière-plan sous le panneau pleine largeur.
C'est là que nous pouvons utiliser le contenu généré. J'ajoute le contenu généré ::before
le conteneur de grille et lui donne une couleur d'arrière-plan. Si je ne fais rien d'autre, cela positionnera le contenu dans la première cellule de la grille.
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); }

Je peux ensuite positionner le contenu en utilisant le positionnement basé sur les lignes pour l'étirer sur la zone qui doit afficher la couleur d'arrière-plan.
.grid::before { content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
Vous pouvez voir l'exemple complet dans ce CodePen.
Voir l'exemple d'arrière-plan du contenu généré par le stylo par Rachel Andrew (@rachelandrew) sur CodePen.
Contrôler la pile avec z-index
Dans l'exemple ci-dessus, le contenu généré est inséré avec ::before
. Cela signifie que les autres éléments viennent après lui, il est au bas de la pile et s'affichera donc derrière le reste du contenu là où je le veux. Vous pouvez également utiliser z-index
pour contrôler la pile. Essayez de changer le sélecteur ::before
en ::after
. L'arrière-plan du contenu généré se trouve maintenant au-dessus de tout, comme vous pouvez le voir à la façon dont la bordure passe sur l'image. C'est parce qu'il est maintenant devenu la dernière chose dans le conteneur de la grille, il est peint en dernier et apparaît donc "en haut".
Pour changer cela, vous devez donner à cet élément une propriété z-index
inférieure à tout le reste. Si rien d'autre n'a de valeur z-index
, la chose la plus simple à faire est de donner à votre contenu généré un z-index
de -1
. Cela l'amènera à être la première chose dans la pile, en tant qu'élément avec le z-index
le plus bas.
.grid::after { z-index: -1; content: ""; background-color: rgba(214,232,182,.3); border: 5px solid rgb(214,232,182); grid-column: 2 / 5; grid-row: 1 / 4; }
L'ajout d'arrière-plans de cette manière ne doit pas nécessairement se limiter à déposer un arrière-plan complètement derrière votre contenu. Pouvoir faire apparaître des blocs de couleur derrière une partie de votre conception pourrait créer des effets intéressants.
Est-ce quelque chose que la spécification pourrait résoudre à l'avenir ?
L'ajout d'arrière-plans et de bordures semble être une fonctionnalité manquante de la spécification CSS Grid et dont le groupe de travail a discuté avec de nombreux membres de la communauté (le fil de discussion est sur GitHub).
Si vous avez des cas d'utilisation qui ne sont pas facilement résolus avec le contenu généré, ajoutez vos réflexions à ce fil. Vos commentaires et cas d'utilisation aident à démontrer que les développeurs s'intéressent à la fonctionnalité et garantissent également que toute proposition couvre le type de choses que vous devez faire.
Plus d'exemples, s'il vous plaît !
Si cet article vous encourage à expérimenter avec le contenu généré ou, si vous avez déjà un exemple, veuillez l'ajouter aux commentaires. Tout le monde est nouveau dans l'utilisation de Grid en production, il y a donc beaucoup de « je n'y ai jamais pensé ! ” des moments à vivre, car nous combinons Grid avec d'autres méthodes de mise en page.