La Cascade

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

:nth-child

par Chris Coyier, 06 septembre 2015, css, pseudo-classes, dico, article original paru le 6 septembre 2011 dans CSS-Tricks

Le sélecteur :nth-child (“n-ième enfant”) permet de sélectionner un ou plusieurs éléments en fonction de leur ordre dans la source et selon des critères que vous déterminez.


Le sélecteur :nth-child (“n-ième enfant”) permet de sélectionner un ou plusieurs éléments en fonction de leur ordre dans la source et selon des critères que vous déterminez. La spécification W3C le range parmi les “pseudo-classes structurelles”, ce qui signifie qu'il est utilisé pour appliquer un style au contenu en fonction de ses relations avec les éléments parents et enfants.

Supposons que nous ayons une grille CSS et que nous voulions retirer la marge sur chaque quatrième module :

//HTML
<section class="grid">
  <article class="module">One</article>
  <article class="module">Two</article>
  <article class="module">Three</article>
  <article class="module">Four</article>
  <article class="module">Five</article>
</section>

Plutôt que d'ajouter une classe à chaque quatrième item, nous pouvons utiliser :nth-child :

//CSS
.module:nth-child(4n) {
  margin-right: 0;
}

Comme vous le voyez, :nth-child prend un argument (c'est le n-ième enfant, mais il faut bien préciser comment on détermine ce n). Cela peut être un simple chiffre, les mots-clés even (pair) ou odd (impair), ou bien une formule.

Si un chiffre est spécifié, seul un élément sera sélectionné, par exemple :nth-child(2) sélectionnerait le deuxième module dans notre HTML ci-dessus.

Si c'est un mot-clé ou une formule, une itération permettra de sélectionner le ou les éléments correspondants. Par exemple, :nth-child(even) sélectionnerait les modules 2 et 4. :nth-child(3n+1) séléctionnerait les modules 1 et 4.

Au passage, on voit ici que :nth-child(even) est l'équivalent de :nth-child(2n) et :nth-child(odd) est l'équivalent de :nth-child(2n+1) - sachant que lorsque la valeur de l'argument est inférieure ou égale à zéro, il n'y a pas de sélection. Inférieure à zéro ? Oui, car on pourrait très bien utiliser une formule du type :nth-child(2n-1) et pour n=0 on aurait un argument égal à -1. Dans ce cas, aucun élément ne serait sélectionné.

Pour illustrer tout ceci, voici quelques exemples de sélecteurs :nth-child :

voir CSS-Tricks: :nth-child by Zachary Kain CodePen

À noter

  • :nth-child procède par itération en commençant par le début de la liste. C'est la seule différence avec :nth-last-child qui commence par la fin de la liste.
  • le sélecteur :nth-child est très proche de :nth-of-type mais avec une différence essentielle : il est moins spécifique. Dans notre premier exemple, il donnerait le même résultat parce que nous ne faisons d'itérations que sur les éléments .module, mais si nous avions un groupe plus complexe, :nth-child essaierait de cibler tous les éléments frères (siblings) et non pas les éléments frères limités au même type. C'est un point important à retenir concernant la puissance de :nth-child : il sélectionne tous les éléments frères et non pas seulement ceux qui sont spécifiés avant les deux-points :. Vous pouvez consulter l'article :nth-of-type pour plus de détails sur la différence entre les deux.

Allons plus loin sur la différence entre les deux

Prenons le HTML suivant :

//HTML
<section>
   <p>Petit</p>
   <p>Cochon</p>    <!-- Celui que je veux -->
</section>

Les deux CSS qui suivent parviendraient au même résultat :

//CSS
p:nth-child(2) { color: red; }

p:nth-of-type(2) { color: red; }

Et pourtant il y a une différence. En bon français, le sélecteur :nth-child nous dit de sélectionner un élément si :

  1. c'est un élément paragraphe
  2. c'est le second enfant d'un parent (quel qu'il soit)

Le sélecteur :nth-of-type, lui, dit ceci :

  1. sélectionner le second paragraphe enfant d'un parent (quel qu'il soit)

:nth-of-type est… comment dire… moins conditionnel.

Admettons que notre balisage soit maintenant :

//HTML
<section>
   <h1>Mots</h1>
   <p>Petit</p>
   <p>Cochon</p>    <!-- Celui que je veux -->
</section>

Ce CSS ne fonctionne plus :

//CSS
p:nth-child(2) { color: red; }

Celui-ci fonctionne encore :

//CSS
p:nth-of-type(2) { color: red; }

Quand je dis qu'il ne fonctionne plus, je veux dire que le sélecteur :nth-child sélectionne maintenant Petit au lieu de Cochon, parce que cet élément répond à la fois à la condition (1) être le deuxième enfant (de <section>) et (2) être un élément paragraphe.

Et quand je dis que le deuxième fonctionne encore, je veux dire que c'est bien Cochon qui est sélectionné, parce que c'est le deuxième paragraphe à l'intérieur de cet élément parent <section>.

Si nous ajoutions un <h2> après le <h1>, le sélecteur :nth-child ne sélectionnerait plus rien du tout parce que maintenant le deuxième enfant n'est plus un paragraphe. Le sélecteur :nth-of-type quant à lui fonctionnerait toujours.

Mon sentiment est que le sélecteur :nth-of-type est moins fragile et plus utile en règle générale, même si :nth-child est plus courant apparemment. Vous vous dites sans doute parfois “je veux sélectionner le second enfant d'un parent si c'est un paragraphe”, mais il y a des chances que vous vouliez plutôt “sélectionner le deuxième paragraphe” ou “sélectionner une ligne sur trois dans le tableau”, et ce sont là des cas où :nth-of-type (à mon avis) est un meilleur choix.

Dernière chose : je me suis rendu compte que la plupart de mes moments de “mais pourquoi ce #@/$!!! de :nth-child ne marche pas ??” venaient du fait que j'avais qualifié le sélecteur avec la balise. Donc lorsque j'utilise :nth-child je préfère en général spécifier le parent et ne pas qualifier :nth-child :

//CSS
dl :nth-child(2) {  } /* est préférable à */
dd:nth-child(2) {  } /* ceci */

Mais bien sûr, tout dépend de la situation exacte.

Quelques recettes

Il existe quelques "testeurs" de :nth-child que vous pouvez vous amuser à utiliser :

CSS-Tricks nth-child tester
Le testeur de Lea Verou
Nth-Test de Paul Maloney

Vous pouvez tester les recettes suivantes :

👉🏾 Sélectionner uniquement le cinquième élément :

//CSS
li:nth-child(5) {
    color: green;
}

👉🏾 Sélectionner tous les éléments sauf les 5 premiers :

//CSS
li:nth-child(n+6) {
    color: green;
}

👉🏾 Sélectionner seulement les 5 premiers éléments :

//CSS
li:nth-child(-n+5) {
    color: green;
}

👉🏾 Sélectionner un élément sur quatre, en commençant par le premier :

//CSS
li:nth-child(4n-7) {  /* or 4n+1 */
    color: green;
}

Autres ressources à consulter sur ce sujet :

Autres articles intéressants :

articles en français :

articles en anglais :

Autres ressources externes

Articles de Chris Coyier traduits dans La Cascade

Voir la page de Chris Coyier et la liste de ses articles dans La Cascade.
Article original paru le 6 septembre 2011 dans CSS-Tricks
Traduit avec l'aimable autorisation de CSS-Tricks et de Chris Coyier.
Copyright CSS-Tricks © 2011