Pseudo-classes CSS pour cibler des enfants (guide clair + exemples)

Les pseudo-classes CSS permettent de sélectionner des éléments selon leur position parmi leurs frères et sœurs, ou selon leur type. Ce guide résume les sélecteurs relationnels (enfant/descendant) puis détaille :first-child, :last-child, :nth-child(), :nth-last-child(), :first-of-type, :last-of-type, :nth-of-type() et leurs pièges courants.

Sélecteurs relationnels (rappel)

Enfants directs

.parent > * {
  /* Tous les enfants directs de .parent */
  border: 1px solid #000;
  margin: 6px;
}

Tous les descendants (enfants + petits-enfants, etc.)

.parent * {
  /* Tous les descendants de .parent */
  color: blue;
}

* > p sélectionne chaque <p> qui est enfant direct de n’importe quel parent… ce qui équivaut pratiquement à p. Préférez p ou un parent précis (.parent > p).

Règles de comptage (très important)

Le comptage commence à 1 (pas à 0).

:nth-child() et :nth-last-child() comptent tous les enfants, peu importe la balise.

Les variantes of-type (ex. :nth-of-type()) comptent seulement les frères du même type de balise.

Mots-clés :

  • odd2n+1impairs (1, 3, 5…)
  • even2npairs (2, 4, 6…)

Premier / dernier enfant :first-child et :last-child

/* 1er et dernier enfant DIRECT d’une liste */
.conteneur ul > :first-child { font-weight: 700; }
.conteneur ul > :last-child  { margin-bottom: 20px; }

/* 1er et dernier <p> ENFANT DIRECT d’un <div> */
div > p:first-child { color: #333; }
div > p:last-child  { color: #666; }

.conteneur ul:first-child cible un <ul> qui est premier enfant de son parent, pas le premier <li> de la liste.

Position par rang : :nth-child() & :nth-last-child()

Exemples simples

/* 3e enfant (quel que soit le type) */
ul li:nth-child(3) { background: #f7f7f7; }

/* Pairs/impairs parmi tous les enfants */
div > p:nth-child(even) { background: #eee; } /* 2,4,6… */
div > p:nth-child(odd)  { background: #f9f9f9; } /* 1,3,5… */

Depuis la fin

/* Pairs en partant de la fin, tous types confondus */
ul li:nth-last-child(even) { color: #444; }

Motifs arithmétiques

/* 1, 11, 21, 31, … (tous les enfants) */
div > *:nth-child(10n + 1) { outline: 1px dashed #999; }

Si vous voulez “chaque 10e <p>”, utilisez plutôt p:nth-of-type(10n+1) (voir section suivante) pour ne pas être perturbé par d’autres balises au même niveau.

Position par type : :first-of-type, :last-of-type, :nth-of-type(), :nth-last-of-type()

Syntaxes correctes (sans parenthèses pour first/last)

/* Premier et dernier élément de CHAQUE type parmi les enfants directs */
.parent > *:first-of-type { border-top: 2px solid #000; }
.parent > *:last-of-type  { border-bottom: 2px solid #000; }

/* Chaque 2e paragraphe (2, 4, 6…) */
.parent > p:nth-of-type(2n) { color: blue; }

/* Spans impairs (1,3,5…) */
.parent > span:nth-of-type(odd) { color: red; }

/* Pair en partant de la fin, parmi les <li> uniquement */
ul > li:nth-last-of-type(even) { font-style: italic; }

Différence clé :

  • :nth-child(3) = 3e enfant, quel que soit son type.
  • p:nth-of-type(3) = 3e <p> (ignore les autres balises).

Exemples pratiques (ciblages utiles)

Le 2e paragraphe seulement si c’est bien un <p>

.article > p:nth-of-type(2) { font-size: 1.05rem; }

Tous les 5e éléments d’une grille… mais seulement les <li>

.grid > li:nth-of-type(5n) { transform: scale(1.02); }

Au survol du conteneur, styliser son 2e <p>

.card:hover > p:nth-of-type(2) { color: #0a84ff; }

N’appliquer le style qu’aux <li> pairs visibles

/* Bonus : éviter certains éléments via :not() si besoin */
ul > li:not(.is-hidden):nth-of-type(even) { background: #f2f2f2; }

Mémo comparatif

Pseudo-classeCompte quoi ?ExempleSélectionne…
:first-child / :last-childTous les enfantsdiv > p:first-childle <p> si c’est le 1er enfant du div
:nth-child(an+b)Tous les enfantsli:nth-child(odd)les éléments 1,3,5…
:nth-last-child(an+b)Tous les enfants (depuis la fin)li:nth-last-child(2)l’avant-dernier élément
:first-of-type / :last-of-typeMêmes balises uniquementp:first-of-typele 1er <p>
:nth-of-type(an+b)Mêmes balises uniquementp:nth-of-type(3)le 3e <p>
:nth-last-of-type(an+b)Mêmes balises (depuis la fin)p:nth-last-of-type(2)l’avant-dernier <p>

Pièges fréquents (et comment les éviter)

  • Pairs/impairs inversés : odd = impairs, even = pairs.
  • Mauvais parent ciblé : ul:first-child ≠ “1er li”. Utilisez ul > li:first-child.
  • Type mélangé : si des balises différentes cohabitent, :nth-child() peut surprendre. Préférez :nth-of-type() quand vous visez un type précis.
  • Espaces mal placés : .conteneur ul :last-child (avec espace) cible le dernier enfant de n’importe quel descendant de ul. Pour le dernier li, utilisez ul > li:last-child.
  • Parenthèses : :first-of-type et :last-of-type n’ont pas de parenthèses.
  • Commentaires CSS : n’oubliez pas de fermer /* … */.

Exercice : petit HTML de test + styles (copiez, testez)

<div class="parent">
  <p>Paragraphe 1</p>
  <span>Span 1</span>
  <p>Paragraphe 2</p>
  <div>
    <p>Paragraphe imbriqué</p>
  </div>
</div>
<ul class="liste">
  <li>Un</li>
  <li>Deux</li>
  <li>Trois</li>
  <li>Quatre</li>
  <li>Cinq</li>
</ul>
/* Enfants directs & descendants */
.parent > * { border: 1px solid #000; margin: 6px; }
.parent *   { color: #222; }

/* Premier/dernier li */
.liste > :first-child { font-weight: 700; }
.liste > :last-child  { color: #0a84ff; }

/* Impairs/pairs (rang, tous types) */
.liste > li:nth-child(odd)  { background: #fafafa; }
.liste > li:nth-child(even) { background: #f0f0f0; }

/* 2e paragraphe uniquement (par type) */
.parent > p:nth-of-type(2) { background: #ffe; }

/* Pattern 10n+1 sur les <li> uniquement */
.liste > li:nth-of-type(10n+1) { outline: 1px dashed #888; }

En bref

  • Choisissez :nth-child() quand la position absolue parmi tous les enfants vous suffit.
  • Préférez :nth-of-type() pour cibler la nième balise d’un type précis.
  • Vérifiez toujours le parent et la structure du DOM : le comptage dépend du voisinage réel.
Catégories : Architecture de l’information & Documentation numérique
Retour en haut