Arkendia Classrooms
Leçon 9 sur 21 · 17 min

Sélecteurs, spécificité, cascade et héritage

Écrire « tous les paragraphes en vert » est simple. Mais comment dire « uniquement le titre du premier projet » ou « les liens du menu, quand on passe dessus » ? Et que se passe-t-il quand deux règles se contredisent ? Cette leçon répond à ces questions : vous apprendrez à cibler les éléments avec précision, et à comprendre pourquoi le navigateur choisit une règle plutôt qu’une autre. C’est l’une des notions les plus importantes du CSS.

Les sélecteurs de base

SélecteurCibleExemple
ÉlémentTous les éléments de ce typep { … }
ClasseLes éléments portant cette classe.carte { … }
IdentifiantL’unique élément portant cet id#contact { … }
UniverselTous les éléments* { … }
GroupePlusieurs sélecteurs à la foish1, h2, h3 { … }

Pour utiliser un sélecteur de classe, on ajoute l’attribut class aux éléments HTML, puis on écrit un point suivi du nom dans le CSS :

<article class="carte">…</article>
<article class="carte carte-vedette">…</article>
.carte {
  background-color: white;
}

.carte-vedette {
  border: 2px solid #e0a96d;
}

Un élément peut avoir plusieurs classes séparées par des espaces, et une même classe peut servir à autant d’éléments que vous voulez. L’id, en revanche, doit être unique dans la page. Privilégiez les classes pour le style : elles sont réutilisables et leur poids est plus faible, ce qui évitera des conflits.

Les combinateurs : cibler selon la position

On peut combiner des sélecteurs pour exprimer la relation entre éléments :

  • Descendant (espace) : nav a cible les liens situés n’importe où dans un nav ;
  • Enfant direct (>) : ul > li cible les li qui sont des enfants immédiats d’un ul ;
  • Frère adjacent (+) : h2 + p cible le paragraphe qui suit directement un h2 ;
  • Frères suivants (~) : h2 ~ p cible tous les paragraphes frères qui suivent un h2.
nav a {
  text-decoration: none;
}

.carte > h3 {
  margin-top: 0;
}

h2 + p {
  font-size: 1.125rem;
}

Les pseudo-classes : cibler un état ou une position

Une pseudo-classe commence par deux-points et décrit un état ou une situation :

  • :hover : le pointeur survole l’élément ;
  • :focus et :focus-visible : l’élément a le focus clavier (nous y reviendrons au chapitre 5) ;
  • :first-child, :last-child, :nth-child(2n) : sélection selon la position ;
  • :not(.cache) : tout ce qui n’a pas cette classe ;
  • :checked, :disabled, :required, :valid, :invalid : états de formulaire.
a:hover {
  text-decoration: underline;
}

tbody tr:nth-child(even) {
  background-color: #f0ebe2;
}

input:invalid {
  border-color: #b3261e;
}

Les pseudo-éléments, eux, utilisent deux deux-points et ciblent une partie d’un élément : ::first-line (première ligne), ::first-letter (première lettre), ::before et ::after (du contenu généré, nous les rencontrerons plus tard).

Les sélecteurs d’attribut

On peut aussi cibler un élément d’après un attribut : a[href^="https"] sélectionne les liens dont l’adresse commence par « https », input[type="email"] les champs de type email, a[target="_blank"] les liens qui s’ouvrent dans un nouvel onglet.

Plusieurs règles, un seul gagnant : la cascade

Que se passe-t-il quand deux règles s’appliquent à un même élément avec des valeurs différentes ? Le mot « cascade » du nom CSS répond : le navigateur applique un ordre de priorité. Il compare, dans l’ordre :

  1. l’origine et l’importance : les styles du navigateur sont les plus faibles, puis viennent ceux de l’auteur du site (vous), et la mention !important inverse les priorités ;
  2. la spécificité du sélecteur : plus un sélecteur est précis, plus il pèse ;
  3. l’ordre d’apparition : à spécificité égale, la dernière règle écrite l’emporte.

Calculer la spécificité

On peut se représenter la spécificité comme un score à trois chiffres (ID, classes, éléments) :

SélecteurIDClasses, attributs, pseudo-classesÉléments
p001
.carte010
nav a:hover012
#contact100
#contact .bouton110

On compare colonne par colonne en commençant par la gauche : un seul identifiant bat n’importe quel nombre de classes, et une seule classe bat n’importe quel nombre d’éléments. Le style en ligne (attribut style) pèse encore plus lourd. Le sélecteur universel * et la pseudo-classe :where() ne comptent pour rien.

p { color: black; }           /* spécificité 0-0-1 */
.intro { color: darkgreen; }  /* spécificité 0-1-0 : gagne */
p.intro { color: navy; }      /* spécificité 0-1-1 : gagne encore */

Un paragraphe <p class="intro"> sera donc bleu marine, quel que soit l’ordre des trois règles.

Attention

Évitez !important. Il fait gagner une déclaration à tout prix, mais oblige ensuite à utiliser lui-même !important pour la contredire : la feuille devient ingérable. Évitez aussi les sélecteurs trop longs (body main section article div p span) : ils sont fragiles et difficiles à surcharger. Une simple classe suffit presque toujours.

L’héritage

Certaines propriétés sont héritées : si vous les appliquez à un élément, ses descendants les reçoivent automatiquement. C’est le cas de color, font-family, font-size, line-height ou text-align. Vous avez déjà vu l’effet : en réglant font-family sur body, toute la page change de police sans que vous ayez à cibler chaque élément.

D’autres propriétés ne sont pas héritées, comme margin, padding, border ou background : ce serait absurde que chaque enfant d’une boîte reçoive à son tour la même bordure. Trois mots-clés permettent de piloter ce comportement :

  • inherit : hérite de la valeur du parent ;
  • initial : revient à la valeur par défaut de la propriété ;
  • unset : agit comme inherit si la propriété est héritée, sinon comme initial.
a {
  color: inherit; /* le lien reprend la couleur du texte qui l’entoure */
}

Structurer sa feuille de style

Pour limiter les conflits de spécificité, adoptez dès maintenant une stratégie simple :

  • écrivez d’abord des règles générales sur des éléments (body, h1, a) ;
  • ajoutez ensuite des classes pour les composants (.carte, .bouton) ;
  • n’utilisez les identifiants que comme ancres de navigation (#contact), pas pour le style ;
  • gardez une spécificité faible et homogène.

Astuce

Dans l’inspecteur, le panneau des styles liste les règles qui s’appliquent à l’élément sélectionné, de la plus prioritaire à la moins prioritaire. Les déclarations barrées sont celles qui ont perdu face à une autre. C’est le meilleur moyen de comprendre un conflit.

À vous de jouer

Voici un fragment de HTML et de CSS :

<article class="carte" id="projet-alpes">
  <h3 class="titre">Les Alpes en hiver</h3>
</article>
h3 { color: black; }
.carte h3 { color: green; }
#projet-alpes .titre { color: red; }
.titre { color: blue; }

De quelle couleur sera le titre ? Calculez la spécificité de chaque règle. Puis, sans toucher à l’identifiant, que faudrait-il changer pour obtenir du bleu ?

Voir une solution

Spécificités : h3 = 0-0-1 ; .carte h3 = 0-1-1 ; #projet-alpes .titre = 1-1-0 ; .titre = 0-1-0. La règle avec l’identifiant gagne : le titre est rouge.

Pour obtenir du bleu, le plus propre est de supprimer le sélecteur par identifiant (on ne stylise pas par id) et de conserver une règle de classe. Si vous deviez absolument conserver la règle rouge, il faudrait une règle plus spécifique que 1-1-0, ce qui est une mauvaise idée : mieux vaut revoir la structure des règles.

À retenir

  • Sélecteurs : élément, classe (.), identifiant (#), universel, groupe, combinateurs (espace, >, +, ~), attributs.
  • Les pseudo-classes (:hover, :nth-child()…) ciblent un état ; les pseudo-éléments (::before…) une partie d’élément.
  • La cascade tranche selon l’importance, la spécificité (ID, classes, éléments) puis l’ordre d’écriture.
  • Certaines propriétés sont héritées (texte), d’autres non (boîtes).
  • Privilégiez des classes simples, évitez !important et les identifiants pour le style.

Dans la prochaine leçon, vous découvrez comment chaque élément est une boîte, et comment mesurer et colorer vos éléments.

Publicité
Connectez-vous pour enregistrer votre progression. Se connecter