Kodokon kodokon.com

Sélecteurs modernes : :has, :is, :where, :nth-child avancé

Exploitez les pseudo-classes fonctionnelles récentes pour sélectionner selon le contenu, regrouper sans exploser la spécificité et cibler des motifs complexes.

9 min · 3 questions

Ouvrir cette leçon dans Kodokon

:is() et :where() regroupent des sélecteurs, mais divergent sur un point décisif : la spécificité. :is(nav, .menu, #main a) prend la spécificité du plus fort de ses arguments (ici l'ID), même si c'est nav qui matche. :where() a une spécificité de zéro, quels que soient ses arguments. Conséquence pratique : :where() est l'outil idéal pour les resets et les styles par défaut d'un design system, que n'importe quel simple sélecteur de classe pourra surcharger sans lutte.

CSS
:where(h1, h2, h3, h4) {
  margin-block: 0;
  line-height: 1.2;
}

:is(article, aside, section) :is(h2, h3) {
  font-family: var(--font-heading);
}

.prose :is(ul, ol) li + li {
  margin-top: 0.5em;
}
Regroupement et contrôle de la spécificité

:has() inverse enfin le sens de lecture : le sélecteur cible l'élément hôte, pas ce qu'il contient. .card:has(> img) sélectionne la carte qui possède une image en enfant direct. Combiné aux pseudo-classes d'état, il permet de remonter l'information sans JavaScript : styler un label quand son champ est invalide, un formulaire quand un champ a le focus, une ligne de tableau quand sa case est cochée.

CSS
.field:has(input:invalid:not(:focus)) label {
  color: #dc2626;
}

.card:has(> img) {
  padding-top: 0;
}

tr:has(input[type="checkbox"]:checked) {
  background: #eef2ff;
}
Sélection selon le contenu ou l'état interne

Sur :nth-child(), deux acquis à consolider. D'abord la lecture des formules An+B : 2n (pairs), 2n+1 (impairs), -n+3 (les trois premiers), n+4 (du quatrième à la fin) ; l'intervalle « du 2e au 5e » s'écrit en combinant :nth-child(n+2):nth-child(-n+5). Ensuite la syntaxe of S, plus récente : :nth-child(2n of .visible) compte uniquement parmi les enfants qui matchent .visible, là où .visible:nth-child(2n) compte tous les enfants puis filtre - deux résultats très différents dès qu'il y a des éléments intercalés.

CSS
tr:nth-child(odd) {
  background: #fafafa;
}

li:nth-child(-n + 3) {
  font-weight: 600;
}

li:nth-child(n + 2):nth-child(-n + 5) {
  border-top: 1px solid #e5e7eb;
}

.row:nth-child(2n of .visible) {
  background: #eef2ff;
}
Formules An+B et syntaxe of S

Quiz de validation

Vérifiez que vous avez bien retenu les points clés de cette leçon.

  1. Quelle est la spécificité de :where(#main, .nav, a) ?
    • Celle de l'ID, soit (1,0,0)
    • La somme des trois arguments
    • Zéro, quels que soient les arguments
    • Celle de l'argument qui matche effectivement
  2. Que sélectionne .card:has(> img) ?
    • Les images enfants directes d'une carte
    • Les cartes qui contiennent une image en enfant direct
    • Les cartes situées après une image dans le DOM
    • Toutes les images descendantes des cartes
  3. Dans une liste où seuls certains li portent .visible, que fait li:nth-child(2n of .visible) ?
    • Il cible les li pairs de la liste qui ont aussi la classe .visible
    • Il cible un li sur deux en ne comptant que les li.visible
    • Il cible les li pairs puis leur ajoute la classe .visible