Utilisation de la spécificité de :where() comme Reset CSS

Je ne sais pas pour vous, mais j’écris ces trois déclarations de nombreuses fois dans mon CSS :

ul {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

Vous pourriez me crier dessus et me dire que je peux simplement les mettre dans mon Reset CSS. J’aimerais pouvoir le faire, mais je ne veux pas le faire et je vais vous dire pourquoi dans une seconde.

Les users-agent attribuent des valeurs à ces propriétés dans une liste dans un but précis, celui de rendre les listes plus lisibles. Voici les styles par défaut dans les navigateurs chrome pour une <ul> élément :

ul {
  list-style-type: disc;
  margin-block-start: 1em;
  margin-block-end: 1em;
  margin-inline-start: 0px;
  margin-inline-end: 0px;
  padding-inline-start: 40px;
}

Ainsi, sans ajouter de classe en HTML ou de style en CSS, nous les obtenons automatiquement. C’est une bonne chose et je ne veux pas la perdre. Mais j’apprécierais de pouvoir faire comprendre au navigateur qu’il y a de très fortes chances que je ne veuille pas de cette fonctionnalité par défaut dans les cas où j’ajoute une classe à l’élément.

Voici donc une solution rapide pour reset un élément <ul> qui a une classe :

ul[class] {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

Maintenant, je ne perds pas le style par défaut, sauf lorsque j’ajoute une classe à mon élément <ul> élément.

Le problème

Il y a un problème avec cette solution. Imaginons qu’il y ait une liste pour laquelle nous voulons avoir une autre class. list-style-type pour elle, comme le suivant :

ul[class] {
  padding: 0;
  margin: 0;
  list-style-type: none;
}

.list {
  list-style-type: square;
}

Cela ne fonctionne pas puisque ul[class] a une plus grande spécificité. C’est là que notre solution s’effondre.

Nous pourrions ajouter plus de poids à la spécificité du sélecteur :

ul.list {
  list-style-type: square; /* Spécificité: 0, 1, 1 */
}

/* or */

.sidebar .list {
  list-style-type: square; /* Spécificité: 0, 2, 0 */
}

Si vous êtes d’accord pour donner plus de poids au sélecteur, vous pouvez le faire. Mais personnellement, je ne suis pas d’accord. Par exemple, je ne veux pas mettre le nom de l’élément dans mon CSS la plupart du temps en raison du principe de séparation des préoccupations. Ou, si vous suivez la méthodologie BEM, des problèmes surviendront très certainement car cela entre en conflit avec elle.

Que pouvons-nous donc faire ?

La solution

Il y a quelques mois, j’ai appris l’existence de certains pseudo-classes, dont les suivants :is() et :where(). Ces deux pseudo-classes fonctionnels ont la particularité de pouvoir modifier la spécificité, ce qui nous donne le pouvoir d’annuler ou d’augmenter cette spécificité.

La clé à propos de :where() est qu’il a toujours une spécificité nulle. Donc on peut se débarrasser de notre problème très facilement comme ça :

:where(ul[class]) {
  list-style: none;
}

.list {
  list-style: square; /* Maintenant ça fonctionne! */
}

Grâce à la puissance de ce sélecteur, les bibliothèques peuvent nous donner un style sans spécificité. Il n’y aurait donc pas de spécificité à concurrencer lorsque nous, auteurs, écrivons du CSS.

Démonstration

Dans la démo suivante, vous pouvez supprimer :where() pour voir ce dont nous avons parlé en action :

Nouveau Tutoriel

Newsletter

Ne manquez jamais les nouveaux conseils, tutoriels et autres.

Pas de spam, jamais. Nous ne partagerons jamais votre adresse électronique et vous pouvez vous désabonner à tout moment.