Enfants et descendants en CSS

Le langage CSS est plutôt simple et intuitif. Mais, en s'habituant à cette aisance d'utilisation, on en oublie parfois certaines de ses subtilités (en tout cas c'est mon cas). En voici une parmi d'autres : la présentation des « enfants » et des « descendants » d'un élément.

Les CSS sont l'outil idéal pour travailler la mise en forme et la présentation d'une page web. A travers l'utilisation de classes, d'identifiants ou simplement avec le nom des différentes balises HTML, on peut décider que tel paragraphe aura telle couleur, que tel bloc s'affichera à tel endroit, etc.

Mais, à l'instar du DOM, les CSS permettent aussi de penser un document (X)HTML comme un arbre hiérarchique dont les différentes parties, les balises HTML, s'imbriquent les unes dans les autres. Si l'on prend l'exemple de cette page web, on pourrait la représenter de manière simplifiée sous la forme suivante :

  • document
    • html
      • head
      • body
        • div#header le titre du site
        • div#content le texte de l'article
        • div#infos le menu de navigation et le pied-de-page
1. Arbre hiérarchique simplifiée de cette page web.

L'une des fonctionnalités du langage CSS est donc d'accéder à certains éléments de cet arbre hiérarchique en les reconnaissant comme étant contenues dans d'autres éléments. Ainsi, tous les éléments d'une page web destinés à s'afficher à l'écran sont contenus dans la balise body ; on dit que ce sont des « descendants » de body. Certains d'entre eux sont aussi des « enfants », et c'est sur cette différence entre « enfants » et « descendants » que nous allons nous arrêter. Pour illustrer le propos, imaginons le code HTML suivant :

<div id="test">
    <p>Paragraphe 1</p>
    <div id="sous-test">
        <p>Paragraphe 2</p>
        <p>Paragraphe 3</p>
        <p>Paragraphe 4</p>
    </div>
    <p>Paragraphe 5</p>
</div>
2. Code HTML de l'exemple.

Nous avons un bloc div test composé d'une série de paragraphes. Certains de ces paragraphes sont inclus dans un autre bloc div (sous-test). Si l'on retranscris le code sous forme d'arbre hiérarchique, nous pouvons le représenter comme suit :

  • #test
    • Paragraphe 1
    • #sous-test
      • Paragraphe 2
      • Paragraphe 3
      • Paragraphe 4
    • Paragraphe 5
3. Arbre hiérarchique de l'exemple.

Intéressons-nous donc à ces paragraphes pour comprendre comment leur appliquer des styles en les considérant comme des enfants et/ou des descendants du bloc test.

Note importante : des styles particuliers seront appliqués à l'arbre hiérarchique de l'exemple pour distinguer enfants et descendants. Ces styles seront visibles par tous les internautes, quelque soit le navigateur qu'ils utilisent mais que cela n'induise pas en erreur : certains navigateurs, et notamment Internet Explorer, ne sont pas capables de rendre toutes les règles CSS décrites ci-dessous.

Les sélecteurs d'enfants et de descendants

Si on se réfère aux définitions du W3C :

  • On appelle un élément A l'enfant de l'élément B, si et seulement si B est le parent de A ;
  • On appelle un élément A un descendant d'un élément B si A est soit (1) un enfant de B, soit (2) un enfant d'un autre élément C qui est lui-même un descendant de B ;

Un enfant A est donc un « descendant direct » d'un élément B. Tout enfant est aussi un descendant, mais tous les descendants ne sont pas forcément des enfants.

La syntaxe CSS pour appliquer des styles à un descendant et/ou à un enfant d'un élément est dés plus simple :

/* Appliquer des styles à A, enfant de B */
B > A { }
/* Appliquer des styles à A, descendant de B */
B A { } 
4. Syntaxe CSS pour appliquer des règles aux enfants ou aux descendants A d'un élément B.

Appliquons donc des styles différents aux paragraphes de l'exemple, avec les enfants de #test en rouge et les descendants soulignés :

/* Paragraphes enfants de test : en ROUGE */
#test > p { color: red; }
/* Paragraphes descendants de test : SOULIGNE */
#test p { text-decoration: underline; }
5. Styles appliqués à l'exemple pour différencier enfants et descendants de #test.
  • #test
    • Paragraphe 1
    • #sous-test
      • Paragraphe 2
      • Paragraphe 3
      • Paragraphe 4
    • Paragraphe 5
6. Visualisation des paragraphes enfants (en rouge) et/ou descendants (soulignés) de #test.

Nous le voyons ici : si tous les paragraphes sont des descendants de #test (tous sont soulignés), seuls les paragraphes 1 et 5 sont ses enfants. Les navigateurs Firefox et Opera sont capables de distingués les deux mais Internet Explorer ne comprend le sélecteur d'enfants.

Pseudo-classe first-child

Les CSS permettent aussi d'accéder à un enfant particulier d'un élément avec la pseudo-classe first-child qui correspond au premier élément enfant d'un autre élément. On peut la combiner avec les sélecteurs d'enfants et de descendants de la manière suivante :

°°stx-css°° /* Appliquer des styles au premier A, enfant de B */ B > A:first-child { } /* Appliquer des styles au(x) premier(s) A, enfant de B ou de tout élément dans B */ B A:first-child { }

7. Syntaxe CSS pour appliquer des règles au(x) premier(s) enfant(s) A d'un élément B ou des éléments appartenant à B.

En appliquant ces règles à notre exemple (premier paragraphe enfant de #test en rouge, premier paragraphe enfant de #test ou de tout autre sous-élément souligné), nous obtenons :

°°stx-css°° /* Premier paragraphe enfant de test : en ROUGE */ #test > p:first-child { color: red; } /* Premiers paragraphes enfants de test ou de tout élément dans test : SOULIGNE */ #test p:first-child { text-decoration: underline; }

8. Styles appliqués à l'exemple pour différencier le premier enfant de #test et les premier(s) enfant(s) de #test et d'élément(s) appartenant à #test.

  • #test
    • Paragraphe 1
    • #sous-test
      • Paragraphe 2
      • Paragraphe 3
      • Paragraphe 4
    • Paragraphe 5
9. Visualisation des premiers paragraphes enfants de test (en rouge) et/ou enfants de #test ou d'éléments appartenant à #test (souligné).

Firefox et Opera comprennent parfaitement la pseudo-classe first-child, mais pas Internet Explorer.

Les évolutions CSS 3

Passons maintenant aux nouveautés qui devraient voir le jour avec la version 3 des CSS. Elles sont encore à l'état d'ébauche et ne sont donc présentées ici qu'à titre d'information.

La pseudo-classe last-child

Nous avons tout d'abord la pseudo-classe :last-child qui est construite sur le même modèle que first-child : elle permet d'identifier le dernier enfant d'un élément.

Bien qu'encore en développement, l'utilisation de cette pseudo-classe mérite d'être illustrée puisque les navigateurs à moteur de rendu Gecko (Firefox, Mozilla et dérivés) la comprennent déjà.

/* Appliquer des styles au dernier A, enfant de B */
B > A:last-child { }

/* Appliquer des styles aux derniers A, enfant de B ou de tout élément dans B */
B A:last-child { }
10. Syntaxe CSS pour appliquer des règles au(x) dernier(s) enfant(s) A d'un élément B ou d'éléments apartenant à B.
/* dernier paragraphe enfant de test : en ROUGE */
#test > p:last-child { color: red; }

/* dernier paragraphe enfant de test ou de tout élément dans test : SOULIGNE */
#test p:last-child { text-decoration: underline; }
11. Styles appliqués à l'exemple pour différencier dernier enfant de #test et dernier(s) enfant(s) de #test et d'élément(s) appartenant à #test.
  • #test
    • Paragraphe 1
    • #sous-test
      • Paragraphe 2
      • Paragraphe 3
      • Paragraphe 4
    • Paragraphe 5
12. Visualisation des derniers paragraphes enfants de test (en rouge) et/ou enfants de #test ou d'éléments appartenant à #test (souligné).

Pseudo-classes nth-child(n) et nth-last-child(n)

Les pseudo-classes nth-child et nth-last-child ont une portée plus générale puisqu'elles permettent d'identifier le énième enfant d'un élément, en partant du début ou de la fin :

Présentation de nth-child() et nth-last-child()
Règles CSS 3 Signification Règles CSS 2
#test> p:nth-child(1) Premier p enfant de #test #test> p:first-child
#test> p:nth-child(2) Deuxième p enfant de #test -
#test> p:nth-last-child(1) Dernier p enfant de #test #test> p:last-child
#test> p:nth-last-child(2) Avant-dernier p enfant de #test -

Pour le moment, aucun navigateur web n'est capable d'appliquer ces règles CSS.

Avantages et limites

Avec les sélecteurs d'enfants et de descendants, la pseudo-classe first-child et les futures last-child ou nth-child, nous disposons donc d'une palette d'outils dés plus intéressante pour distingués certains éléments d'une page web. Utilisés seuls ou combinés, ils permettent de pointer précisément un élément ou bien d'éviter de déclarer des classes à de multiples reprises.

Enfin en théorie car, comme on l'a vue, certaines de ces propriétés ne sont absolument pas comprises par le navigateur web le plus répandu au monde : Internet Explorer. On en est donc réduit à (1) éviter d'utiliser ces outils ou (2) compenser les lacunes du navigateur de Microsoft en ajoutant des classes ou des identifiants afin d'appliquer des styles à certains éléments particuliers.

Ressources et références

Titre
CSS 2.1 Specification
Auteurs
Bert BOS
Auteurs
Tantek ÇELIK
Auteurs
Ian HICKSON
Auteurs
Lie WIUM
Editeur
W3C
Date
Chapitre
5. Les sélecteurs
Titre
Selectors Level 3
Auteurs
Tantek ÇELIK
Auteurs
Elika ETEMAD
Auteurs
Daniel GLAZMAN
Auteurs
Ian HICKSON
Auteurs
Peter LINSS
Auteurs
John WILLIAMS
Editeur
W3C
Date
Chapitre
Structural pseudo-classes