Cette traduction est incomplète. Aidez à traduire cet article depuis l'anglais.

Dans l'article précédent, nous avons vu les différents sélecteurs CSS. Au fur et à mesure de leur utilisation, il pourra arriver que plusieurs règles, plusieurs sélecteurs s'appliquent au même élément. Dans un tel scénario, quelle règle CSS sera appliquée à l'élément ? Pour répondre à cette question, nous aurons besoin de voir les concepts de cascade et d'héritage. Dans cet article, nous traitons de la cascade, du poids des sélecteurs et de la façon dont les propriétés héritent les unes des autres selon les différentes règles.

CSS signifie Cascading Style Sheets (ce qui signifie « feuilles de style en cascade »). L'acronyme de CSS met donc en avant la notion de cascade. Pour simplifier à l'extrême, la cascade indique l'ordre d'importance des règles CSS. Analysons plus en détails ce que cela signifie.

La cascade

La mise en forme finale d'un élément peut ếtre obtenue grâce à plusieurs règles présentes à plusieurs endroits et qui interagissent de façon complexe. C'est cette complexité qui rend CSS si puissant mais c'est également une source de confusion et de difficultés lorsqu'il s'agit de résoudre des problèmes.

Plusieurs sources d'informations principales forment cette cascade. Ces sources sont :

  1. Les styles par défaut du navigateur pour le langage à balise utilisé
  2. Les styles définis par l'utilisateur qui consulte le document
  3. Les styles liés au document par l'auteur (en HTML, cela correspond aux éléments <link> qui pointent vers les feuilles de style externes)
  4. Les styles définis par l'auteur via la balise <style> dans l'élément <head>
  5. Les styles définis par l'auteur qui sont directement appliqués depuis les éléments (en HTML, cela correspond à utiliser l'attribut style)

Chaque source surcharge les précédentes, dans cet ordre. Les styles définis par les utilisateurs surchargent les styles par défaut du navigateur, les styles définis par les auteurs surchargent les styles définis par les utilisateurs et les navigateurs. Les styles « individuels » au sein des éléments les surchargent tous (navigateurs, utilisateurs et auteurs via la balise <link> et la balise <style>). Voici la règle générale de la cascade, si vous souhaitez en explorer les détails, veuillez lire notre article dédié à la cascade CSS.

CSS permet de marquer certaines propriétés comme étant importantes. Ces propriétés, quel que soit l'endroit de la cascade où elle se situent, surchargeront les autres. Cela casse la cascade naturelle et l'utilisation d'un tel marquage est donc considéré comme une mauvaise pratique.

body {
  color: pink !important;
}

Le poids des sélecteurs

Les règles de la cascade s'appliquent pour prioriser les différentes sources. Que se passe-t-il si, pour une même source, plusieurs règles concernent le même élément ? Dans ce cas, pour prioriser les règles, on prendra en compte le poids du sélecteur. Le poids d'un sélecteur est calculé en fonction de sa spécificité :

  1. Niveau 1 : Sélecteur d'identifiant
  2. Niveau 2 : Sélecteur de classe, de pseudo-classe et d'attribut
  3. Niveau 3 : Sélecteur de type et de pseudo-element

Le sélecteur universel (*), les combinateurs (+, >, ~, ' ') et la pseudo-classe de négation (:not) n'ont aucun effet sur la spécificité d'un sélecteur.

Pour déterminer si une règle s'applique plutôt qu'une autre on regarde :

  1. celle qui possède le plus de sélecteurs de niveau 1
  2. si le nombre de sélecteurs de niveau 1 est le même : celle qui possède le plus de sélecteurs de niveau 2
  3. si le nombre de sélecteur de niveau 2 est le même : celle qui possède le plus de sélecteurs de niveau 3
  4. enfin, si les sélecteurs ont le même poid, ce sera l'ordre des règles dans le fichier source qui importera : la règle la plus basse dans le fichier l'emportera sur une règle déclarée avant.

Prenons ce fragment de HTML par exemple :

<p id="cookie" class="crispy">Ce cookie est <span>délicieux !</span></p>

Poids de niveau 1

Cette feuille de style illustre ce qui se passe lorsqu'un sélecteur de niveau 1 entre en conflit avec d'autres sélecteurs :

/* Ce sélecteur est composé d'un sélecteur de niveau 1
   Poids : 1 | 0 | 0 */
#cookie {
  color: green;
}

/* Ce sélecteur n'a aucun sélecteur de niveau 1 
   et 2 sélecteur de niveau 2
   Poids : 0 | 2 | 0 */
[id=cookie].crispy {
  color: red;
}

/* 1|0|0 > 0|2|0 : La première règle s'applique et le texte
   est vert. Un seul sélecteur de niveau 1 sera toujours
   prioritaire par rapport à X sélecteurs de niveau 2. */

Le résultat obtenu est donc :

Au vu de ce « poids », certains développeurs web considèrent qu'utiliser des sélecteurs d'identifiant est une mauvaise pratique. Mieux vaut éviter d'utiliser plus d'un sélecteur d'identifiant par règle.

Poids complexe

Dans l'exemple précédent, nous avons utilisé la notation x|y|z pour indiquer le poids de chaque sélecteur. Cette notation permet de comparer les poids des sélecteurs simplement : en comparant chaque colonne, en commençant par celle de gauche. Voyons un exemple plus complexe où cette notation est appréciable :

/* 0|1|1
   Zéro sélecteur de niveau 1
   Un sélecteur de niveau 2 (.crispy)
   Un sélecteur de niveau 3 (span)
   On rappelle ici que le combinateur >
   n'a aucun impact pour calculer le
   poids */
.crispy > span {
  color: red;
}

/* 0|1|2 
   Zéro sélecteur de niveau 1
   Un sélecteur de niveau 2 (:nth-child)
   Deux sélecteurs de niveau 3 (p, span) */
p span:nth-child(1) {
  color: red
}

/* 0|1|2
   Zéro sélecteur de niveau 1
   Un sélecteur de niveau 2 (:nth-child)
   Deux sélecteurs de niveau 3 (p, em) 
   Là aussi, le sélecteur universel (*) et
   la pseudo-classe :not pseudo-class ne comptent
   pas (mais le sélecteur em avec :not est
   compté) */
p *:nth-child(1):not(em) {
  color: green
}

/* La première règle a un poids inférieur. Les deux 
   règles qui suivent ont le même poids. C'est donc
   l'ordre du code qui importent et la dernière 
   règle surchargera la deuxième */

L'héritage

L'héritage en CSS est le dernier morceau du puzzle pour comprendre comment un style est appliqué à un élément. L'héritage s'applique de deux façons et chacune a son importance : le mélange des règles et l'héritage entre propriétés.

Le mélange des règles

Lorsque plusieurs règles correspondent au même éléments, elles s'appliquent toutes à cet élément. Nous avons vu avec la cascade comment déterminer quelle règle surcharge quelle autre. Cette surcharge ne concerne que les propriétés en conflit, sinon, toutes les règles sont appliquées.

Prenons un exemple :

Voici le code HTML :

<p>Je suis<strong> important</strong></p>

Appliquons cette feuille de style CSS :

/* 0|0|2 */
p strong {
  background-color: khaki;
  color: green;
}

/* 0|0|1 */
strong {
  text-decoration: underline;
  color: red;
}

/* À cause de son poids, la première règle surcharge la propriété
   color de la deuxième règle. Toutefois, la couleur d'arrière plan
   fournie par la première règle et la décoration fournie par la 
   seconde s'appliquent à l'élément strong. Vous verrez également 
   que le texte de l'élément est mis en gras grâce aux styles 
   par défaut du navigateur. */

Le résultat obtenu est le suivant :

L'héritage entre propriétés

L'héritage entre propriétés est un peu plus subtil. Certaines propriétés appliquées à un élément peuvent hériter de la valeur d'un des éléments parents. Cela permet par exemple de déterminer la valeur qui sera appliquée pour la propriété d'un élément quand aucune n'est fournie (la valeur du parent se « propage » à l'élément enfant). L'héritage permet d'avoir à éviter de définir toutes les règles pour tous les éléments à chaque fois.

L'héritage peut avoir lieu pour toutes les propriétés mais certaines sont héritées « naturellement » comme color ou font-family. La valeur basique, par défaut, est définie par la feuille de style du navigateur, toutes les propriétés qui héritent « naturellement » prendront cette valeur par défaut si rien d'autre n'est spécifié.

Pour savoir si l'héritage d'une propriété CSS est naturel, consultez notre référence CSS.

CSS fournit trois valeurs spéciales pour gérer l'héritage :

  • inherit : cette valeur indique que la valeur de la propriété de l'élément sera la même que la valeur de la propriété de l'élément parent (c'est la valeur par défaut pour tous les éléments dont l'héritage est naturel).
  • initial : cette valeur indique que la valeur de la propriété de l'élément sera la valeur définie par la feuille de style du navigateur (si la valeur n'est pas définie par la feuille de style du navigateur et que l'héritage de cette propriété est naturel, la valeur définie sera alors une copie de l'héritage naturel plutôt qu'inherit. Les effets de bords engendrés peuvent être plutôt subtils et nous ne les verrons pas ici).
  • unset : cette valeur réinitialise la propriété avec sa valeur natuelle. Cela signifie que si la propriété est héritée naturellement, on aura le même effet qu'inherit, sinon on aura le même effet qu'avec initial.

C'est la valeur inherit qui va nous intéresser le plus ici car elle permet de déclarer explicitement l'héritage de la propriété d'un élément par rapport à son parent.

Illustrons ce concept avec un exemple :

Voici le code HTML utilisé :

<ul>
  <li>Couleur par défaut <a href="#">pour le lien</a></li>
  <li class="inherit">Couleur héritée <a href="#">pour le lien</a></li>
  <li class="initial">Couleur réinitialisée <a href="#">pour le lien</a></li>
  <li class="unset">Couleur non définie <a href="#">pour le lien</a> color</li>
</ul>

Et voilà la feuille de style CSS appliquée :

/* On définit la couleur verte pour le corps.
   La propriété color est naturellement héritée,
   tous les fils de l'élément body auront donc
   cette même couleur verte */
body {
  color: green;
}

/* On remarquera ici que le navigateur fixe la couleur
   du lien (bleu) plutôt que d'utiliser l'héritage 
   naturel de la propriété color. C'est pour cette
   raison que le premier lien de notre exemple est bleu.*/

/* Ici, on déclare explicitement que le lien contenu 
   dans un élément héritera de son parent (ici pour
   propriété color). Cela signifie ici que la couleur
   du lien sera héritée de celle de son parent, l'élé-
   ment li, qui hérite naturellement de celle de ul,
   qui hérite naturellement de celle de l'élément body
   et c'est celle-ci qui est verte (comme on l'indique
   avec la règle précédente).*/
.inherit a {
  color: inherit;
}

/* Avec cette règle, pour tous les liens contenus dans
   un élément dont la classe vaut initial, on définit leur
   couleur avec la valeur initiale. Généralement la couleur
   initiale des textes du navigateur est noire. */
.initial a {
  color: initial
}

/* Enfin, pour tous les liens qui sont contenus dans un
   élément de classe unset, on utilise unset. La propriété
   color étant naturellement héritée, cela est équivalent
   au résultat obtenu avec inherit. On a donc, dans ce cas,
   des liens qui ont la même couleur que le corps : vert.*/
.unset a {
  color: unset;
}

Le résultat obtenu est le suivant :

La suite

Félicitations, vous commencez à plonger dans toute la profondeur et la richesse de CSS. Vous connaitrez bientôt tous les concepts qui gouvernent CSS, vous pouvez d'ores et déjà commencer à étudier CSS en pratique. Si vous souhaitez parcourir les dernières étapes de ce chemin théorique, vous pouvez continuer cette série pour découvrir le modèle de boîte CSS pour manipuler la disposition du contenu en CSS.

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : edspeedy, SphinxKnight, jumperparis
 Dernière mise à jour par : edspeedy,