Niveau : Débutant

Comprendre l'héritage et la parenté des styles CSS

Les styles CSS fonctionnent sur le principe d'imbrication, de parenté et d'héritage, quelques explications.

Tutoriel par (Intégrateur du Dimanche, Strasbourg)
Créé le , mis à jour le (156932 lectures)
Tags : css, cascade, ancêtre

Le modèle Parent-Enfant(s)

L'héritage des CSS est fondé sur le modèle Parent-Enfant(s) : chaque élément Enfant reçoit en héritage tous les styles de son élément Parent. Par exemple, la balise <html> est parent de <body>, et <table> est parent de <tr> qui lui-même est parent de <td>. Cet héritage est très pratique et permet d'éviter beaucoup de répétitions inutiles : en effet, en attribuant une propriété à un parent (par exemple font-size: 1.5em), elle sera transmise à tous ses enfants, mais aussi aux enfants de ces enfants, etc...

Précision : l'élément enfant héritera de toutes les propriétés de l'élément parent uniquement si ces propriétés s'héritent, car l'héritage ne fonctionne pas non plus sur toutes les propriétés css (margin, padding et autres propriétés de bloc)

Voici un exemple illustrant bien ce principe d'héritage. J'applique une propriété à la balise <html> et elle se transmet à l'enfant <body> et à <div> qui est enfant de <body>:

<style type="text/css">
<!--
   html {font-size: 1.5em;}
-->
</style>

Le code HTML :

<body>
   test
   <div>test</div>
</body>

Pour connaitre les différents liens de parenté des balises, il existe un site très complet à ce sujet.

Attention : il existe des exceptions, toutes les balises ne peuvent pas être imbriquées !

Cas de la balise de lien <a>

L'héritage s'applique aussi à la balise de liens <a>. Ses enfants sont les pseudo-classes suivantes :

  • :link (lien par défaut)
  • :visited (lien déjà visité)
  • :hover (lien au survol)
  • :active (lien actif)

Les propriétés appliquées à la balise parent <a> se transmettent donc aux enfants. Le code suivant est donc inutile et redondant :

a {
  text-align: center;
  font-size: 1em;
  text-decoration: none;
  color: blue;
  margin: 0 5px;
}
a:hover {
  text-align: center;
  font-size: 1em;
  text-decoration: underline;
  color: red;
  margin: 0 5px;
}

Vous pouvez vous contenter de ce code :

a {
  text-align: center;
  font-size: 1em;
  text-decoration: none;
  color: blue;
  margin: 0 5px;
}
a:hover {
  text-decoration: underline;
  color: red;
}

L'Héritage par imbrication des Classes ou des Id

Comme il existe un héritage entre les différentes balises HTML existantes, il est également tout à fait possible d'appliquer cet héritage à vos classes personnalisées ou à vos id.

Pour cela, il suffit dans votre code CSS d'écrire les classes les unes à côté des autres séparées par un espace: la première sera parente de la deuxième, qui sera parente de la troisième, etc... à condition que chacune soit imbriquée dans l'autre au sein de votre code HTML

Quelques précisions : les éléments enfants sont affectés tant que cet élément enfant n'a pas une valeur propre d'affectée pour la propriété. Par exemple, en mettant un color:red à <body>, tout les textes seront rouges sauf pour les éléments dont on a donné une autre valeur a color.

Exemple 1 :

.menu li {
  propriétés
}

<li> sera enfant de la classe .menu. Cela va affecter tous les éléments <li> contenus dans la classe .menu et uniquement ceux-là.

Cela évite d'écrire <li class="menu"> pour chaque élément de la liste.

Exemple 2 :

li .menu {
  propriétés
}

".menu" sera enfant de la balise <li>. Cela va affecter tous les éléments de classe "menu" contenus dans un <li>

Attention à ne pas confondre avec :

li, .menu {
  propriétés
}

Ici, il n'y a plus de notion d'héritage si les éléments sont séparés par une virgule. Cet exemple va signifier ".menu" OU <li>. Cela va affecter tous les éléments de classe "menu" du document, ainsi que toutes les balises <li> du document s'il y en a.

Attention à ne pas confondre non-plus avec :

li.menu {
  propriétés
}

Ici, cela ne va concerner que les <li> de classe "menu" il s'agit purement et simplement de l'équivalent du "ET" : les deux conditions doivent être réunies pour fonctionner. Il n'y a plus de notion d'héritage. Il ne faut donc pas oublier l'espace.

Exemple 3 :

div.menu a:hover {
  propriétés
}

Traduction : je veux définir ":hover", enfant de la balise <a>, elle-même enfant de la classe ".menu" appliquée au bloc parent <div>. Cela va affecter uniquement les liens survolés ("a:hover") contenus dans les <div> de classe ".menu"

En fait, on peut se demander s'il est vraiment nécessaire de définir toute l'arborescence. En effet, les blocs conteneurs sont la plupart du temps des balises <div>, donc il est peu utile de les préciser dans vos héritages.

Que l'on note ".menu li" ou "li" cela ne changera rien au niveau de l'héritage (au niveau du ciblage oui, car on ne définit pas le meme élément dans la page), mais sinon, dans tous les cas, le <li> héritera de ses parents, peu importe quels sont ces éléments parents

Mais sachez toutefois que le code HTML suivant ne sera PAS pris en compte avec la CSS définie en exemple 3 parce que le conteneur parent est une balise <p> et non un <div>:

<p class="menu">
  <a href="lien.html">lien</a>
</p>

Exemple d'utilisation : un menu

Voici comment utiliser ces notions d'héritages à travers un menu :

body {
  margin: 10px;
  padding: 0;
  font: 14px Verdana, sans-serif;
}
.menu {
  list-style-type: none;
}
.menu li {
  float: left;
}
.menu a {
  margin: 0 2px;
  width: 100px;
  height: 20px;
  display: block;
  text-align: center;
  border: 1px solid gray;
  text-decoration: none;
  color: #000;
  background: #fff;
}
.menu a:hover {
  background: #ccc;
  border: 1px solid gray; 
}
.menu a:active {
  background: gray;
  color: #fff;
}

Le code HTML :

<body>

  <ul class="menu">
  <li><a href="">Menu 1</a></li>
  <li><a href="">Menu 2</a></li>
  <li><a href="">Menu 3</a></li>
  <li><a href="">Menu 4</a></li>
  </ul>

</body>

Le cas des polices relatives : em, %,...

Il est recommandé d'utiliser des tailles de polices relatives (em principalement) afin de permettre aux mal-voyants de pouvoir agrandir ces tailles à leur convenance.

Les unités em et % sont relatives à la police de référence : 1 em est égal à la taille de cette police.

Cependant, il faut bien comprendre que la taille de la police de référence se transmet par héritage également : dans le cas d'éléments imbriqués, la police de référence change à chaque nouveau conteneur.

Par exemple (voir code ci-dessous), si vous définissez une taille de référence de 2em dans le <body>, puis une autre taille de 2em dans un élément enfant du body (par exemple <table>, les textes contenus dans le tableau auront une taille de 2em par rapport à 2em, soit 4em ! Et ainsi de suite si vous cumulez les imbrications de balises enfants.

<style type="text/css">
body {font-size: 2em;}
table {font-size: 2em;}
</style>

<body>

texte de 2em (référence : body)
<table>
  <tr>
    <td>texte de 2em (référence : table inclue dans body)</td>
  </tr>
</table>
</body>