La Cascade

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

Des styles de listes créatifs

par Michelle Barker, 5 septembre 2022, design, html, css, accessibilite, semantique, article original paru le 24 août 2022 dans webdev

Un aperçu de quelques façons utiles et créatives de styliser une liste.


Que nous vient-il à l'esprit lorsque nous pensons à une liste ? Le premier exemple peut-être, le plus évident, est la liste de courses — la plus simple des listes, une collection d'articles sans ordre particulier. Mais nous utilisons les listes de toutes sortes de façons sur le Web. Une série de concerts à venir ? Très probablement une liste. Un processus de réservation en plusieurs étapes ? Sans doute une liste. Une galerie d'images ? Même elle pourrait être considérée comme une liste d'images avec des légendes.

Dans cet article, nous allons nous plonger dans les différents types de listes HTML disponibles sur le Web et savoir quand les utiliser, y compris certains attributs que vous ne connaissez peut-être pas. Nous examinerons également quelques façons utiles et créatives de leur appliquer un style avec CSS.

Quand utiliser une liste ?

Un élément de liste HTML doit être utilisé lorsque des éléments doivent être regroupés de manière sémantique. Les technologies d'assistance (comme les lecteurs d'écran) signaleront à l'utilisateur la présence d'une liste et le nombre d'éléments. Si vous pensez, par exemple, à une grille de produits sur un site d'achat, connaître cette information serait très utile. Par conséquent, l'utilisation d'un élément de liste pourrait être un bon choix.

Types de liste

En ce qui concerne le balisage, nous avons le choix entre trois éléments de liste différents :

  • Liste non ordonnée
  • Liste ordonnée
  • Liste de description

Le choix de l'une ou l'autre dépend du cas d'utilisation.

Liste non ordonnée (ul)

L'élément liste non ordonnée (<ul>) est le plus utile lorsque les éléments de la liste ne correspondent à aucun ordre particulier. Par défaut, il s'affiche sous la forme d'une liste à puces. Un exemple est une liste de courses, où l'ordre n'a pas d'importance.

Une liste de courses, non ordonnée

Un exemple plus courant sur le Web est le menu de navigation. Quand on crée un menu, il convient d'envelopper le ul dans un élément nav et d'identifier le menu avec une étiquette, pour aider les technologies d'assistance. Nous devons également identifier la page actuelle dans le menu, ce que nous pouvons faire en utilisant l'attribut aria-current :

<nav aria-label="Navigation principale">
  <ul>
    <li>
      <a href="/page-1" aria-current="page">Elément de menu 1</a>
    </li>
    <li>
      <a href="/page-2">Elément de menu 2</a>
    </li>
    <li>
      <a href="/page-2">Menu élément 2</a>
    </li>
    ...
  </ul>
</nav>

Cet article sur la structure des menus présente un certain nombre de recommandations pour garantir que nos menus de navigation soient accessibles à tous.

Liste ordonnée (ol)

Un élément de liste ordonnée (<ol>) est le meilleur choix lorsque l'ordre des éléments est important, comme dans le cas d'un processus en plusieurs étapes. Par défaut, les éléments de la liste sont numérotés. Un exemple pourrait être un ensemble d'instructions, où les étapes doivent être accomplies dans l'ordre.

Une liste d'instructions pour préparer le thé, avec un numéro d'ordre
voir Ordered list de Web.dev dans CodePen

Les éléments <ol> et <ul> ne peuvent contenir que des éléments <li> comme enfants directs.

Liste de description (dl)

Une liste de description contient des termes (éléments <dt>) et des descriptions (<dd>). Chaque terme peut être accompagné de plus d'une description. Les cas d'utilisation possibles pourraient inclure un glossaire de termes, ou peut-être un menu de restaurant. Les listes de descriptions ne sont pas affichées avec des marqueurs par défaut, bien que les navigateurs aient tendance à indenter l'élément <dd>.

En HTML, il est permis de regrouper des termes avec les descriptions qui les accompagnent à l'aide d'un élément <div>. Cela peut être utile à des fins de style, comme nous le verrons plus tard.

<dl>- Ceci est valide -->
<dl>
    <dt>Terme 1</dt>
    <dd>C'est la première description du premier terme de la liste</dt>.
    <dd>C'est la deuxième description du premier terme de la liste</dt>
    <dt>Terme 2</dt>
    <dd>C'est la description du deuxième terme de la liste</dd>
</dl>

<!-- Ceci est également valable -->
<dl>
    <div>
        <dt>Terme 1</dt>
        <dd>C'est la première description du premier terme de la liste</dd>.
        <dd>C'est la deuxième description du premier terme de la liste</dd>
    </div>
    <div>
        <dt>Terme 2</dt>
        <dd>C'est la description du deuxième terme de la liste</dd>
    </div>
</dl>

Style de liste simple

L'une des utilisations les plus simples d'une liste est dans un bloc de texte du <body>. Très souvent, ces listes simples n'ont pas besoin d'un style élaboré, mais nous pourrions vouloir personnaliser les marqueurs d'une liste ordonnée ou non ordonnée dans une certaine mesure, par exemple avec une couleur de marque (brand), ou en utilisant une image personnalisée pour nos puces. Nous pouvons faire beaucoup de choses avec list-style et le pseudo-élément ::marker !

Pour vous rafraîchir la mémoire sur les bases du style de liste, consultez le tutoriel de web.dev Apprendre le CSS, ainsi qu'une plongée en profondeur dans l'utilisation de ::marker dans ce guide sur les puces personnalisées. Continuez à lire pour découvrir des choses que vous ne savez peut-être pas encore !

::marker

En plus de donner à nos marqueurs de liste un style de base, nous pouvons créer des puces cycliques. Ici, nous utilisons trois URL d'images différentes pour la valeur de contenu du pseudo-élément ::marker, ce qui ajoute à l'aspect manuscrit de notre exemple de liste de courses (au lieu d'utiliser une seule image pour tout) :

::marker {
  content: url('/marker-1.svg') ' ';
}

li:nth-child(3n)::marker {
  content: url('/marker-2.svg') ' ';
}

li:nth-child(3n - 1)::marker {
  content: url('/marker-3.svg') ' ';
}

Compteur personnalisé

Pour certaines listes ordonnées, nous pourrions vouloir utiliser la valeur du compteur, mais y ajouter une autre valeur. Nous pouvons utiliser le compteur list-item comme valeur pour la propriété content de notre marqueur et y ajouter tout autre contenu :

::marker {
  content: counter(list-item) '🐈 ';
}

Nos compteurs s'incrémentent automatiquement de un, mais nous pouvons leur permettre de s'incrémenter d'une valeur différente si nous le souhaitons, en définissant la propriété counter-increment sur l'élément de la liste. Par exemple, ceci incrémentera nos compteurs de trois à chaque fois :

li {
  counter-increment: list-item 3;
}

Nous pourrions approfondir bien d'autres choses avec les compteurs. L'article Listes, marqueurs et compteurs CSS de Rachel Andrew explique certaines des possibilités plus en détail.

Limites de la stylisation de ::marker

Nous souhaitons parfois avoir plus de contrôle sur la position et le style de nos marqueurs. Il n'est pas possible de positionner le marqueur à l'aide de flexbox ou de grid, par exemple, ce qui peut parfois être un inconvénient si vous avez besoin d'un autre alignement. ::marker expose un nombre limité de propriétés CSS pour le style. Si notre conception nécessite autre chose qu'un style de base, il est préférable d'utiliser un autre pseudo-élément.

Styliser des listes qui ne ressemblent pas à des listes

Parfois, nous souhaitons donner à nos listes un style totalement différent du style par défaut. C'est souvent le cas avec un menu de navigation, par exemple, où nous souhaitons généralement supprimer tous les marqueurs, et pourrions afficher notre liste horizontalement, à l'aide de flexbox. Une pratique courante consiste à régler la propriété list-style sur none. Cela signifie que le pseudo-élément ::marker ne sera plus accessible dans le DOM.

Attention
Un mot d'avertissement : list-style : none fera que Safari ne reconnaîtra plus une liste non ordonnée dans l'arbre d'accessibilité, et par conséquent qu'un lecteur d'écran n'annoncera plus les informations utiles telles que le nombre d'éléments. Une solution simple (en supposant que votre liste doive être lue comme telle) consiste à utiliser role="list" sur l'élément* <ul> ou <ol> *de votre HTML, comme le recommande l'expert en accessibilité Scott O'Hara.*

Marqueurs personnalisés avec ::before

L'utilisation du pseudo-élément ::before était un moyen courant de créer des marqueurs de liste personnalisés avant l'arrivée de ::marker. Mais même aujourd'hui, il peut nous offrir plus de flexibilité, lorsque nous en avons besoin, pour le style visuellement complexe des listes.

Comme pour ::marker, nous pouvons ajouter nos propres styles de puce personnalisés en utilisant l'attribut content. Contrairement à l'utilisation de ::marker, nous devons effectuer un positionnement manuel, car nous ne bénéficions pas des avantages automatiques offerts par list-style-position. Mais nous pouvons la positionner relativement facilement avec flexbox, ce qui ouvre un plus grand nombre de possibilités d'alignement. Par exemple, nous pourrions alterner la position du marqueur :

voir Alternating list de Web.dev dans CodePen

Si nous stylisons une liste ordonnée à l'aide de l'élément ::before, nous pouvons également souhaiter utiliser des compteurs pour ajouter nos marqueurs numériques.

li::before {
  counter-increment: list-item;
  content: counter(list-item);
}
voir Alternating list de Web.dev dans CodePen

L'utilisation de ::before au lieu de ::marker nous permet d'accéder pleinement aux propriétés CSS pour un style personnalisé, ainsi que de permettre des animations et des transitions — pour lesquelles la compatibilité est limitée pour ::marker.

Attributs de liste

Les éléments de listes ordonnées acceptent certains attributs facultatifs, qui peuvent nous aider dans bon nombre de cas d'utilisation.

Listes inversées

Si nous disposons d'une liste des 10 meilleurs albums de l'année dernière, nous pourrions vouloir effectuer un compte à rebours de 10 à 1. Nous pourrions utiliser des compteurs personnalisés pour cela, et les incrémenter négativement. Ou bien nous pourrions simplement utiliser l'attribut reversed dans le HTML. Je dirais qu'il est généralement plus judicieux, d'un point de vue sémantique, d'utiliser l'attribut reversed plutôt que d'incrémenter négativement le compteur dans le CSS, à moins que les compteurs n'aient qu'une valeur de présentaton. Si le CSS ne se charge pas, vous verrez quand même les chiffres décomptés correctement dans le HTML. En outre, nous devons tenir compte de la manière dont un lecteur d'écran interpréterait la liste.

Prenez cette démonstration des 10 meilleurs albums de 2021. Si les compteurs étaient incrémentés uniquement à l'aide de CSS, une personne accédant à la page à l'aide d'un lecteur d'écran pourrait en conclure que les chiffres comptent vers le haut, de sorte que le numéro 10 est en fait le numéro 1.

voir Reversed list de Web.dev dans CodePen

Vous pouvez voir dans la démo qu'en utilisant l'attribut inversé, nos marqueurs ont déjà la valeur correcte, sans aucun effort supplémentaire de notre part ! Mais si nous créons des marqueurs de liste personnalisés en utilisant le pseudo-élément ::before, nous devons ajuster nos compteurs. Il nous suffit d'indiquer à notre compteur list-item de s'incrémenter négativement :

li::before {
  counter-increment: list-item -1;
  content: counter(list-item);
}

Diviser les listes

L'attribut start nous permet de spécifier la valeur numérique à partir de laquelle la liste doit commencer. Cela peut notamment être utile dans les cas où vous souhaitez diviser une liste en groupes.

Reprenons notre exemple des 10 meilleurs albums. Peut-être voulons-nous en fait décompter les 20 meilleurs albums, mais par groupes de 10. Entre les deux groupes, il y a un autre contenu de page.

Une liste partagée en deux, avec un autre contenu entrte les deux.

Nous devrons créer deux listes distinctes dans notre HTML, mais comment nous assurer que les compteurs seront corrects ? Dans l'état actuel de notre balisage, les deux listes compteront de 10 à 1, ce qui n'est pas ce que nous voulons. Cependant, dans notre HTML, nous pouvons spécifier une valeur d'attribut de début (start). Si nous ajoutons une valeur de départ de 20 à notre première liste, les marqueurs seront à nouveau mis à jour automatiquement !

<ol reversed start="20">
  <li>...</li>
  <li>...</li>
  <li>...</li>
</ol>
voir Reversed and split list de Web.dev dans CodePen

Affichage de la liste sur plusieurs colonnes

La disposition en plusieurs colonnes se prête parfois bien à nos listes, comme vous pouvez le constater dans les démos précédentes. En définissant une largeur de colonne, nous pouvons faire en sorte que notre liste soit automatiquement réactive et ne s'étende sur deux colonnes ou plus que lorsque l'espace est suffisant. Nous pouvons également définir un espace entre les colonnes et, pour une touche supplémentaire, ajouter une règle de colonne stylisée (en utilisant une abréviation similaire à la propriété border) :

ol {
  columns: 25rem;
  column-gap: 7rem;
  column-rule: 4px dotted turquoise;
}

En utilisant des colonnes, nous pouvons parfois nous retrouver avec des ruptures disgracieuses dans nos éléments de liste — pas toujours l'effet recherché.

Une liste répartie sur plusieurs colonnes.

Nous pouvons empêcher ces ruptures forcées en utilisant break-inside : avoid sur nos éléments de liste :

li {
  break-inside: avoid;
}

Propriétés personnalisées

Les propriétés personnalisées CSS offrent un large éventail de possibilités pour le style des listes. Si nous connaissons l'index de l'élément de la liste, nous pouvons l'utiliser pour calculer les valeurs des propriétés. À l'heure actuelle malheureusement, il n'existe aucun moyen de déterminer l'index de l'élément (de manière utilisable en CSS uniquement, en tout cas). Les compteurs nous permettent uniquement d'utiliser leur valeur dans la propriété content, et ne permettent pas les calculs.

Mais nous pouvons définir l'index de l'élément dans l'attribut style de notre HTML, ce qui peut rendre les calculs plus réalisables, surtout si nous utilisons un langage de templating. Cet exemple montre comment nous pourrions définir cela en utilisant Nunjucks :

<ol style="--length : items|length">
  {% for item in items %}
  <li style="--i : {{ loop.index }}">...</li>
  {% endfor %}
</ol>

Splitting.js est une bibliothèque qui exécute une fonction similaire du côté client.

En utilisant la valeur de la propriété personnalisée, la progression dans une liste peut être affichée de différentes manières. Une façon pourrait être une barre de progression pour une liste d'étapes. Dans cet exemple, nous utilisons un pseudo-élément avec un dégradé linéaire afin de créer une barre pour chaque élément qui indique à quel point l'utilisateur est avancé dans la liste.

li::before {
  --stop: calc(100% / var(--longueur) * var(--i));
  --color1: deeppink;
  --couleur2: rose;

  content: '';
  background: linear-gradient(
    to right,
    var(--color1) var(--stop),
    var(--color2) 0
  );
}

Nous pouvons également ajuster la teinte à mesure qu'on progresse dans la liste, en utilisant la fonction de couleur hsl(). Nous pouvons calculer la valeur de la teinte en utilisant notre propriété personnalisée.

Stylisation de la liste des descriptions

Comme nous l'avons mentionné précédemment, nous pouvons choisir d'envelopper les termes et leurs définitions dans une div ou dans une dl, pour nous donner plus d'options de style. Par exemple, nous pourrions vouloir afficher notre liste sous forme de grille. Si vous définissez display : grid sur la liste sans placer une div autour de chaque groupe, les termes et les descriptions seront placés dans des cellules de grille différentes. C'est parfois utile, comme dans l'exemple suivant, qui montre un menu de tartes avec leurs descriptions.

Nous pouvons définir une grille sur la liste elle-même et nous assurer que les termes et les descriptions seront toujours alignés en colonnes, la largeur de la colonne étant déterminée par le terme le plus long.

voir Pie menu de Web.dev dans CodePen

D'un autre côté, si nous voulons regrouper distinctement les termes avec leurs descriptions à la manière d'une carte, un wrapper <div> est très utile.

voir Pie menu de Web.dev dans CodePen

Ressources complémentaires

Autres ressources externes

Articles de Michelle Barker traduits dans La Cascade

Voir la page de Michelle Barker et la liste de ses articles dans La Cascade.
Article original paru le 24 août 2022 dans webdev
Traduit avec l'aimable autorisation de webdev et de Michelle Barker.
Copyright webdev © 2022