:nth-child
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
:
À 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 :
- c'est un élément paragraphe
- c'est le second enfant d'un parent (quel qu'il soit)
Le sélecteur :nth-of-type
, lui, dit ceci :
- 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 :
- MDN : :nth-child
- Référence SitePoint (en anglais)
- CSS Reference Codrops (en anglais)
- Wiki W3C (en anglais)
- Spécification W3C (en anglais)
Autres articles intéressants :
articles en français :
- Le sélecteur :nth-child, vidéo par Grafikart
articles en anglais :
- nthmaster, quelques exemples complexes d'utilisation des pseudo-classes structurelles :nth
- Usefil :nth-child recipes, de Chris Coyier, quelques recette utiles