Styliser une ligne sur deux dans un tableau, ou mettre en avant seulement le troisième élément d'une liste, semble anodin, mais demande un outil capable de compter. C'est exactement ce que fait la pseudo-classe :nth-child(), grâce à une formule mathématique compacte.
Elle a la réputation d'être intimidante à cause de sa syntaxe an+b, alors qu'une poignée d'exemples suffit à la rendre parfaitement lisible au quotidien.
Définition
La pseudo-classe :nth-child() cible un élément selon sa position parmi les enfants de son parent, en comptant tous les types de balises confondus. Elle accepte un mot-clé simple comme odd ou even, ou une formule de la forme an+b.
Comprendre la formule an+b
Dans la formule, n représente un compteur qui commence à 0 et augmente indéfiniment (0, 1, 2, 3...), a est le multiplicateur, et b est un décalage ajouté au résultat. En remplaçant n par chaque valeur entière, la formule produit la liste des positions ciblées.
/* une ligne sur deux, les pairs : 2, 4, 6... */
tr:nth-child(2n) {
background-color: #f5f5f5;
}
/* une ligne sur deux, les impairs : 1, 3, 5... */
tr:nth-child(2n + 1) {
background-color: white;
}
/* un élément sur trois : 3, 6, 9... */
li:nth-child(3n) {
border-bottom: 2px solid #ddd;
}
/* uniquement le troisième élément */
li:nth-child(3) {
font-weight: bold;
}Avec 2n, la formule produit 0, 2, 4, 6, ce qui correspond aux positions paires puisque les positions commencent à 1 dans le HTML. Avec 2n + 1, elle produit 1, 3, 5, 7, les positions impaires. Un nombre seul, sans n, cible une seule position fixe, comme :nth-child(3) pour le troisième enfant uniquement.
La différence avec :nth-of-type
:nth-child() compte tous les enfants du parent, quel que soit leur type de balise, tandis que :nth-of-type() ne compte que les éléments du même type que celui ciblé. Sur un parent qui mélange des balises différentes, comme un titre suivi de plusieurs paragraphes, ces deux pseudo-classes peuvent donner des résultats très différents pour la même formule.
| HTML | p:nth-child(2) | p:nth-of-type(2) |
|---|---|---|
h2, p, p, p | Aucun résultat (la position 2 est un p, mais le h2 compte aussi) | Le deuxième p, position 3 |
:nth-child() ne semble cibler aucun élément alors que la formule paraît correcte, vérifiez que le parent ne mélange pas d'autres types de balises. Dans ce cas, :nth-of-type() est souvent le choix qui correspond réellement à l'intention.Zébrer un tableau proprement
L'exemple le plus courant de :nth-child() reste le zébrage d'un tableau, où une ligne sur deux reçoit un fond légèrement différent pour faciliter la lecture d'un grand nombre de lignes. Cette technique appartient à la même famille que les autres Pseudo-classe qui décrivent une position, et se marie bien avec une list-style personnalisée quand la formule s'applique à une liste plutôt qu'à un tableau.
tbody tr:nth-child(odd) {
background-color: #fafafa;
}
tbody tr:nth-child(even) {
background-color: #ffffff;
}Cette formule fonctionne quel que soit le nombre de lignes du tableau, sans jamais avoir besoin de recalculer les positions manuellement quand une ligne est ajoutée ou supprimée, ce qui en fait une solution bien plus robuste qu'une classe posée à la main sur chaque ligne paire.
Questions fréquentes
La formule :nth-child(n + 2) cible tout à partir de la deuxième position, ce qui exclut le premier élément. Elle peut ensuite se combiner avec :not(:last-child) pour exclure aussi le dernier.
odd et even à la place d'une formule ?Oui, :nth-child(odd) équivaut exactement à :nth-child(2n + 1), et :nth-child(even) équivaut à :nth-child(2n), ce qui rend le code plus lisible pour ces deux cas très courants.
Pas avec :nth-child(), qui compte toujours depuis le début. Pour compter depuis la fin, il existe une pseudo-classe distincte, :nth-last-child(), qui utilise la même syntaxe de formule. Elle est notamment pratique pour cibler les derniers éléments d'une liste sans connaître leur nombre total.