Listes CSS, marqueurs et compteurs

Publié: 2022-03-10
Résumé rapide ↬ Le style des listes en CSS est plus complexe que vous ne le pensez. Dans cet article, Rachel commence par examiner les listes dans CSS et passe à certaines fonctionnalités intéressantes définies dans la spécification CSS Lists - marqueurs et compteurs.

Les listes en CSS ont des propriétés particulières qui nous donnent le style de liste standard que nous attendons. Une liste non ordonnée gagne une liste à puces, du type disc , et les listes ordonnées sont numérotées. Mon intérêt pour l'exploration plus détaillée des listes est venu d'un travail que j'ai effectué pour documenter le pseudo-élément ::marker pour MDN. Ce pseudo-élément est livré dans Firefox 68 et est publié aujourd'hui . Avec le pseudo-élément ::marker à notre disposition, nous pouvons commencer à faire des choses intéressantes avec les listes, et dans cet article, j'expliquerai plus.

Déconstruire une liste

Vous n'avez peut-être pas beaucoup pensé aux listes, même si nous les utilisons fréquemment dans notre balisage. Beaucoup de choses peuvent être balisées assez logiquement sous forme de liste. Alors que les instructions pas à pas ou les éléments classés peuvent naturellement être décrits par une liste ordonnée <ol> , de nombreux éléments d'une conception peuvent être décrits à l'aide d'une liste non ordonnée <ul> . Une utilisation très courante de l'élément, par exemple, consiste à baliser la navigation, car il s'agit d'une liste de destinations sur le site. Pour notre exploration, commençons par découvrir exactement ce qu'est une liste en CSS.

Comme pour beaucoup de choses en CSS, les listes ont des valeurs initiales qui leur sont appliquées. Ces valeurs les font ressembler à une liste. Ces valeurs spéciales commencent par l'information qu'un élément de liste a la propriété display avec une valeur list-item . Cela crée une boîte au niveau du bloc, avec une boîte de marqueur supplémentaire. La zone de marqueur est l'endroit où la puce ou le numéro de la liste est ajouté.

Plus après saut! Continuez à lire ci-dessous ↓

Les listes ont été définies très tôt dans CSS, et une grande partie de la définition des listes telles que nous les utilisons aujourd'hui provient de CSS2. La spécification CSS2 décrit un élément de liste comme suit :

"Un élément avec display: list-item génère une boîte de bloc principale pour le contenu de l'élément et, selon les valeurs de list-style-type et list-style-image , éventuellement aussi une boîte de marqueur comme indication visuelle que l'élément est un élément de liste.

La boîte de bloc principale est la boîte principale de l'élément et contient tous les enfants, car un élément de liste peut contenir d'autres balises. La case marqueur est alors placée par rapport à cette case principale. La spécification poursuit en détaillant le fait que toute couleur de fond ne sera que derrière cette case principale, et non le marqueur. De plus, le marqueur peut être défini sur l'une des plages de valeurs prédéfinies :

  • disc
  • circle
  • square
  • decimal
  • decimal-leading-zero
  • lower-roman
  • upper-roman
  • lower-greek
  • lower-latin
  • upper-latin
  • armenian
  • georgian
  • lower-alpha
  • upper-alpha
  • none
  • inherit

La spécification d'affichage de niveau 3 définit display: list-item avec les autres valeurs possibles pour la propriété display . Il fait référence à CSS 2.1 - comme le font de nombreuses propriétés et valeurs CSS qui proviennent de CSS2 - mais décrit le mot-clé list-item comme "amenant l'élément à générer un pseudo-élément ::marker ".

La spécification de niveau 3 introduit également la possibilité de créer un élément de liste en ligne avec la syntaxe à deux valeurs utilisée display: inline list-item . Ceci n'est pas encore implémenté par les navigateurs.

Création de zones de marqueur sur des éléments non répertoriés

Comme pour les autres valeurs de display , il est parfaitement valide de donner à tout élément HTML un type d'affichage list-item (si vous souhaitez générer un pseudo-élément ::marker sur l'élément). Cela ne fera pas de l'élément un élément de liste sémantiquement, mais à la place, il ne s'affichera que visuellement en tant qu'élément de liste, et pourra donc avoir un ::marker . Lorsque nous discuterons du pseudo-élément ::marker ci-dessous, vous découvrirez des cas où donner display: list-item à d'autres éléments peut être utile.

La spécification de niveau 3 des listes CSS : ::marker And Counters

La spécification display étend et clarifie la définition des listes que nous trouvons dans CSS2, cependant, il existe également une spécification qui définit le comportement des listes en détail : la spécification CSS Lists Specification Level 3. Comme le comportement de base des éléments de liste est défini dans display , cela détails de la spécification la boîte de marqueur générée lorsque quelque chose a display: list-item avec les compteurs qui sont utilisés par défaut chaque fois que vous créez une liste ordonnée. Certaines fonctionnalités potentiellement utiles sont accessibles via ces fonctionnalités.

Le pseudo-élément ::marker

Le pseudo-élément ::marker vous permet de cibler le marqueur de liste — séparément du contenu de l'élément de liste. Cela n'était pas possible dans les versions précédentes de CSS, par conséquent, si vous modifiiez la couleur ou la taille de la police de ul ou li , cela modifierait également la couleur et la taille de la police des marqueurs. Afin de faire quelque chose d'aussi simple que d'avoir des puces de liste de couleurs différentes du texte, cela impliquerait soit d'envelopper le contenu de l'élément de liste dans une étendue (ou d'utiliser une image pour le marqueur).

 ul { color: #00b7a8; } ul span { color #333; }

Avec le pseudo-élément ::marker , la chose la plus simple que vous pourriez vouloir essayer est d'avoir une puce différente de la couleur du texte, ce qui signifie qu'au lieu du code de l'exemple ci-dessus, vous pouvez utiliser :

 ul { color: #333; } ul ::marker { color: #00b7a8; }

Vous pouvez également utiliser une taille et font-family différentes pour la numérotation d'une liste ordonnée.

 ol ::marker { font-size: 200%; color: #00b7a8; font-family: "Comic Sans MS", cursive, sans-serif; }

Vous pouvez voir tout cela dans un navigateur compatible en utilisant mon exemple CodePen :

Voir le Pen [Puces de couleur avec et sans marqueur](https://codepen.io/rachelandrew/penVJQyoR) de Rachel Andrew.

Voir les balles Pen Colored avec et sans marqueur de Rachel Andrew.

Vous pouvez utiliser le pseudo-élément ::marker sur des éléments non répertoriés. Dans le code ci-dessous, j'ai défini un titre à display: list-item . Cela lui donne une balle et donc une case ::marker à cibler.

J'ai changé la puce pour utiliser un emoji :

 h1 { display: list-item; } h1::marker { content: ""; } 
En-tête avec un chat emoji à sa gauche
Dans Firefox, vous pouvez voir l'emoji utilisé comme marqueur.

Voir le Pen [Heading and marker](https://codepen.io/rachelandrew/pen/wLyyMG) de Rachel Andrew.

Voir le Pen Heading et le marqueur de Rachel Andrew.

Dans l'exemple ci-dessus, j'ai utilisé le contenu généré dans les règles du marqueur. Seul un petit sous-ensemble de propriétés CSS est disponible pour une utilisation sur ::marker . Celles-ci incluent les propriétés de police et la couleur, mais elles incluent également la propriété de content , pour inclure le contenu généré.

L'ajout du content comme propriété autorisée pour ::marker est récent, cependant, il est inclus dans l'implémentation de Firefox. L'inclusion signifie que vous pouvez faire des choses comme inclure une chaîne de texte dans un ::marker . Cela soulève également des possibilités supplémentaires de formatage des marqueurs lorsque vous combinez l'utilisation de compteurs avec ::marker .

Prise en charge du navigateur et solutions de repli

Pour les navigateurs qui ne prennent pas en charge le pseudo-élément ::marker , le repli est le marqueur normal qui aurait été affiché de toute façon. Malheureusement, nous ne pouvons pas actuellement utiliser les requêtes de fonctionnalités pour détecter la prise en charge de sélecteurs tels que ce pseudo-élément pour le moment, bien qu'un problème ait été soulevé concernant l'ajout de cela à la spécification. Cela signifie que vous ne pouvez pas bifurquer votre code pour faire une chose lorsque vous avez du support et autre chose si vous n'en avez pas. Dans la plupart des cas, revenir au marqueur régulier sera une solution raisonnable.

Compteurs

Les listes ordonnées ont une numérotation de liste - quelque chose qui est réalisé au moyen d'un compteur CSS. La spécification CSS Lists décrit donc également ces compteurs. Nous pouvons accéder et créer nous-mêmes des compteurs qui, combinés au pseudo-élément ::marker , peuvent nous donner des fonctionnalités utiles. Ces compteurs peuvent également être utilisés dans du contenu généré régulièrement (non ::marker ).

Si j'ai une liste numérotée d'étapes (et que je voudrais écrire "Étape 1", "Étape 2", etc.), je peux le faire en utilisant le contenu généré dans mon marqueur et en ajoutant le compteur list-item , cela représente le compteur intégré :

 ::marker { content: "Step " counter(list-item) ": "; } 
Une liste ordonnée avec l'étape 1, l'étape 2, etc., avant chaque élément de la liste
Dans Firefox, vous verrez le compteur précédé du mot « Step ».

Voir le Pen [Compteurs et marqueur](https://codepen.io/rachelandrew/pen/BgRaoz) de Rachel Andrew.

Voir les Pen Counters et le marqueur de Rachel Andrew.

Compteurs imbriqués

Si vous avez des listes imbriquées, une façon courante de les numéroter est d'avoir l'élément de niveau supérieur un nombre entier, (1), puis les éléments enfants comme (1.1, 1.2) et leurs enfants (1.1.1, 1.1.2), etc. Vous pouvez y parvenir en utilisant davantage de fonctionnalités de compteurs.

Lorsque vous imbriquez des listes HTML, vous vous retrouvez avec plusieurs compteurs du même nom, imbriqués les uns dans les autres. Le nid de compteurs est accessible à l'aide de la fonction counters() .

Dans le code ci-dessous, j'utilise des counters() pour formater mes marqueurs de liste comme décrit ci-dessus. Le premier argument de counters() est le nom du compteur à utiliser. J'utilise le compteur list-item intégré. Le deuxième argument est une chaîne - c'est ce qui sera concaténé entre les compteurs de sortie (j'utilise un . ). Enfin, j'ajoute un : en dehors de la fonction de compteur mais à l'intérieur de la valeur de content afin que la sortie de mon compteur soit séparée du contenu par deux points.

 ::marker { content: counters(list-item,'.') ':'; color: #00b7a8; font-weight: bold; }

Cela me donne la sortie comme dans l'image. Si vous utilisez un navigateur qui prend en charge ::marker et counters, vous pouvez le voir fonctionner dans l'exemple CodePen - essayez de changer la chaîne d'un . à autre chose pour voir comment cela change la sortie.

Un ensemble de listes imbriquées
Dans Firefox, vous verrez une numérotation de liste imbriquée séparée par des points.

Voir le Pen [Nested counters](https://codepen.io/rachelandrew/pen/VJbwxL) de Rachel Andrew.

Voir les compteurs Pen Nested de Rachel Andrew.

Quelle est la différence entre counter() et counters() ?

La fonction counter() que nous avons utilisée dans le premier exemple pour écrire nos étapes utilise uniquement le compteur le plus interne. Par conséquent, dans la situation où vous avez un ensemble de listes imbriquées, vous écrirez le compteur lié au niveau auquel vous vous trouvez actuellement.

La fonction counters() écrit essentiellement toute cette branche et vous donne la possibilité de concaténer une chaîne entre les compteurs de la branche. Donc, si vous avez un élément de liste avec un compteur de 2 (qui fait partie d'une liste imbriquée dans un élément de liste avec un compteur de 4 ), alors la branche contient :

  • 4
  • 2

Vous pouvez afficher ceci en tant que 4.2 dans le marqueur en utilisant :

 ::marker { content: counters(list-item,'.'); }

Compteurs sur d'autres éléments

Les compteurs peuvent être utilisés sur des choses qui ne sont pas des listes — soit pour produire un marqueur — auquel cas l'élément devra avoir display: list-item — soit pour produire du contenu généré régulièrement. Les compteurs sont largement utilisés dans la production de livres, afin de permettre la numérotation des chapitres et des figures. Il n'y a aucune raison de ne pas adopter une approche similaire sur le web, en particulier pour les articles plus longs.

Les propriétés CSS définies dans la spécification CSS Lists qui traitent de ces compteurs sont :

  • counter-set
  • counter-reset
  • counter-increment

Pour voir comment ceux-ci fonctionnent en dehors des listes, nous pouvons examiner un exemple d'utilisation de compteurs pour numéroter les titres d'un document.

La première chose que je dois faire est de créer un compteur pour les en-têtes sur l'élément body - prêt à l'emploi. J'utilise la propriété counter-reset pour ce faire. Les propriétés counter-reset et counter-set sont très similaires. La propriété counter-reset créera un nouveau compteur si un compteur du nom spécifié n'existe pas déjà, mais créera également des compteurs imbriqués comme décrit ci-dessus si un compteur de ce nom existe. La propriété counter-set ne créera un nouveau compteur que s'il n'y a pas de compteur de ce nom. Pour cela, utiliser l'une ou l'autre propriété fonctionnerait très bien, cependant, counter-set n'a pas un aussi bon support de navigateur que counter-reset , donc je prends la voie pratique :

 body { counter-reset: heading-counter; }

Maintenant que j'ai un compteur, je peux alors utiliser la propriété counter-increment sur le sélecteur pour les en-têtes ; cela devrait incrémenter le compteur chaque fois que le sélecteur correspond.

 h2 { counter-increment: heading-counter; }

Pour voir la valeur, je dois la sortir dans le document. Je peux le faire en utilisant le contenu généré et en l'ajoutant before l'en-tête, comme indiqué dans l'exemple CodePen suivant :

 h2::before { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; } 

Voir le Pen [Titres et compteurs](https://codepen.io/rachelandrew/pen/gNGjxq) de Rachel Andrew.

Voir les Pen Headings and counters de Rachel Andrew.

Alternativement, je pourrais faire de l'élément h2 un élément de list-item , puis utiliser ::marker , comme illustré ci-dessous. Comme déjà détaillé, l'utilisation de l'élément ::marker a une prise en charge limitée du navigateur. Dans Firefox, vous devriez voir le compteur utilisé comme marqueur pour le titre, tandis que d'autres navigateurs afficheront la puce par défaut.

 h2 { display: list-item; } h2::marker { content: counter(heading-counter) ": "; color: #00b7a8; font-weight: bold; } 

Voir le Pen [Titres, marqueurs et compteurs](https://codepen.io/rachelandrew/pen/pXWZay) de Rachel Andrew.

Voir les en-têtes de stylo, les marqueurs et les compteurs de Rachel Andrew.

Compteurs sur les éléments de formulaire

Il y a aussi un peu d'interactivité que vous pouvez réaliser en utilisant CSS Counters - quelque chose que vous pourriez penser que vous avez besoin de JavaScript pour le faire.

J'ai un formulaire qui contient plusieurs champs obligatoires. Le statut requis peut être sélectionné en CSS avec une pseudo-classe :required , et le fait qu'un champ n'a pas été renseigné peut être détecté grâce à la pseudo-classe :invalid . Cela signifie que nous pouvons vérifier les champs qui sont à la fois obligatoires et non valides, et incrémenter un compteur. Ensuite, affichez-le en tant que contenu généré.

Voir le Pen [Counting required form fields](https://codepen.io/rachelandrew/pen/vqpJdM) par Rachel Andrew.

Voir les champs de formulaire requis pour le comptage des stylos par Rachel Andrew.

L'utilité de cela en réalité est discutable - étant donné que nous ne pouvons rien faire avec cette valeur autre que de la coller dans le contenu généré. Il existe également des inquiétudes quant au fait que le contenu généré soit inaccessible à certains lecteurs d'écran, par conséquent, toute utilisation qui est plus que décorative devrait garantir d'autres moyens d'accéder à ces informations. Lisez « Accessibility Support For CSS Generated Content » et les informations les plus récentes « CSS Content Property Screen Reader Compatibility » pour plus de détails concernant l'accessibilité et le contenu généré.

Cependant, cela démontre que les compteurs peuvent réaliser des choses plus utiles que de simples listes de numérotation. Il se peut qu'un jour ces connaissances soient utiles pour résoudre un problème sur lequel vous travaillez.

En savoir plus

Cet article s'est retrouvé assez loin des listes de style, malgré le fait que tout ce que j'ai décrit se trouve dans la spécification CSS Lists. Vous pouvez trouver plus d'informations sur les choses décrites dans les liens ci-dessous. Si vous avez trouvé une utilisation intéressante pour CSS Counters, ou si vous pensez à des choses pour lesquelles vous pourriez utiliser ::marker , ajoutez une note dans les commentaires.

  • ::marker
  • counter-set
  • counter-reset
  • counter-increment
  • « Utilisation des compteurs CSS », documentation Web MDN
  • "Compter avec des compteurs CSS et une grille CSS", CSS-Tricks