Niveau 3 — La Cascade

L'héritage

Comprendre quelles propriétés CSS se transmettent aux enfants, et comment contrôler cette transmission.

1. Comprendre l'héritage

En une phrase : L'héritage CSS est le mécanisme par lequel certaines propriétés se transmettent automatiquement d'un élément parent à ses enfants, sans qu'on ait besoin de les redéfinir.

Imagine une famille : les parents transmettent certaines caractéristiques à leurs enfants (couleur des yeux, taille), mais pas d'autres (nom de famille, adresse). C'est pareil en CSS : certaines propriétés se propagent dans l'arbre DOM, d'autres restent à l'élément qui les définit.

L'héritage joue un rôle crucial dans la cascade : c'est le mécanisme de dernier recours quand aucune règle ne cible directement un élément.

Arbre DOM et héritage :
━━━━━━━━━━━━━━━━━━━━━━

  <body>  ← color: blue (défini ici)
    │
    ├── <h1>  ← hérite color: blue ✓
    │     └── <span>  ← hérite color: blue ✓
    │
    ├── <p>   ← hérite color: blue ✓
    │     └── <strong>  ← hérite color: blue ✓
    │
    └── <div class="special"> ← hérite color: blue ✓
          └── <a href="#">   ← hérite color: blue ✓
                                (mais le navigateur a sa propre
                                 valeur par défaut pour <a>)

Les propriétés héritées se propagent de parent en enfant dans l'arbre DOM

2. Syntaxe détaillée

2.1 Propriétés qui s'héritent

Règle : La plupart des propriétés liées au texte et à la typographie s'héritent. Elles concernent principalement le contenu de l'élément.
Propriété Description Exemple de valeur
color Couleur du texte #1e293b
font-family Police de caractères 'Arial', sans-serif
font-size Taille de police 16px
font-weight Épaisseur de la police bold
font-style Style de police italic
line-height Interligne 1.6
text-align Alignement du texte center
text-transform Transformation du texte uppercase
text-decoration Décoration du texte underline
text-indent Retrait de première ligne 2em
letter-spacing Espacement entre lettres 0.05em
word-spacing Espacement entre mots 0.1em
visibility Visibilité de l'élément hidden
cursor Type de curseur pointer
direction Direction du texte rtl
white-space Gestion des espaces nowrap

2.2 Propriétés qui ne s'héritent PAS

Règle : La plupart des propriétés liées à la mise en page, aux marges, aux bordures et au dimensionnement ne s'héritent PAS. Chaque élément doit les définir explicitement.
Propriété Description Valeur par défaut
margin Marge extérieure 0
padding Marge intérieure 0
border Bordure none
width Largeur auto
height Hauteur auto
background Arrière-plan transparent
display Mode d'affichage inline
position Positionnement static
overflow Débordement visible
z-index Empilement auto
box-shadow Ombre none
border-radius Arrondi 0
opacity Opacité 1
transform Transformation none

2.3 Les mots-clés d'héritage

4 mots-clés permettent de contrôler explicitement l'héritage des propriétés.

inherit

/* Force l'héritage de la valeur du parent */
.special-link {
  color: inherit;    /* prend la couleur du parent au lieu de la valeur par défaut bleue */
}

/* Exemple concret */
<div style="color: red;">
  Texte rouge
  <a href="#" style="color: inherit;">Lien rouge aussi</a>
</div>

initial

/* Remet à la valeur initiale du spéculaire CSS (la valeur par défaut du spec) */
.no-margin {
  margin: initial;    /* = 0 (la valeur initiale de margin dans le spec CSS) */
}

/* Attention : initial ≠ la valeur du navigateur */
/* La valeur initiale de "visibility" est "visible" */
/* La valeur par défaut du navigateur peut être différente */

unset

/* Comportement dynamique :
   - Si la propriété est héritée → se comporte comme inherit
   - Si la propriété n'est pas héritée → se comporte comme initial */

/* Exemple : */
.parent {
  color: red;           /* héritée */
  margin: 20px;         /* non héritée */
}

.enfant {
  color: unset;         /* → inherit → prend red du parent */
  margin: unset;        /* → initial → remet à 0 */
}

revert

/* Remet à la valeur de l'origine précédente dans la cascade */
/* - En author stylesheet → revert à la valeur user stylesheet
   - En user stylesheet → revert à la valeur user-agent
   - En user-agent → revert à nothing (invalide) */

/* Cas d'usage principal : annuler un style générique */
h1 {
  all: revert;   /* annule tous les styles author, revient aux styles navigateur */
}

all (propriété raccourcie)

/* Propriété raccourcie qui agit sur TOUTES les propriétés */
.reset-total {
  all: unset;       /* annule toutes les propriétés */
  all: initial;     /* remet toutes les propriétés à leur valeur initiale */
  all: revert;      /* revient aux styles de l'origine précédente */
  all: revert-layer; /* (CSS Cascade Layers) */
}

/* Très puissant mais dangereux — à utiliser avec précaution */

3. Visualisation

3.1 Tableau comparatif hérité / non hérité

┌─────────────────────────────────┬──────────────────────────────────┐
│   ✅ HÉRITÉES                   │   ❌ NON HÉRITÉES                │
├─────────────────────────────────┼──────────────────────────────────┤
│ color                           │ margin                           │
│ font-family                     │ padding                          │
│ font-size                       │ border                           │
│ font-weight                     │ width / height                   │
│ font-style                      │ background                       │
│ line-height                     │ display                          │
│ text-align                      │ position                         │
│ text-transform                  │ overflow                         │
│ text-decoration                 │ z-index                          │
│ letter-spacing                  │ box-shadow                       │
│ word-spacing                    │ border-radius                    │
│ visibility                      │ opacity                          │
│ cursor                          │ transform                        │
│ direction                       │ list-style (partiellement)       │
│ white-space                     │ vertical-align                   │
│ quotes                          │ clear                            │
│ font-variant                    │ float                            │
│ text-shadow                     │ outline                          │
│ word-break                      │ box-sizing                       │
└─────────────────────────────────┴──────────────────────────────────┘

Les propriétés héritées concernent le texte, les non héritées concernent la mise en page

3.2 Diagramme de décision

Valeur d'une propriété sur un élément enfant :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  1. Règle CSS ciblant directement l'élément ?
     ├── OUI → utiliser cette valeur
     └── NON ↓

  2. La propriété est-elle héritée ?
     ├── OUI → prendre la valeur du parent (héritage)
     │         └── Le parent a-t-il une valeur ?
     │              ├── OUI → utiliser la valeur héritée
     │              └── NON → continuer vers le grand-parent
     └── NON ↓

  3. Utiliser la valeur initiale du spéculaire CSS
     (la valeur par défaut du standard)

Comment le navigateur détermine la valeur d'une propriété

4. Exemples progressifs

4.1 Héritage de la couleur

Démonstration : La couleur se transmet aux enfants

.parent-rouge {
  color: #dc2626;
  font-size: 18px;
  line-height: 1.6;
}

Paragraphe enfant — hérite la couleur rouge et la taille

Span enfant — hérite aussi la couleur rouge

Sous-conteneur — hérite toujours la couleur rouge

Élément strong — hérite la couleur rouge

Analyse : Tous les descendants héritent color, font-size et line-height du parent.

4.2 Non-héritage du margin

Démonstration : Le margin ne se transmet PAS

.parent-margin {
  margin: 20px;       /* ne se transmet PAS aux enfants */
  padding: 10px;      /* ne se transmet PAS aux enfants */
  background: #e2e8f0;
}

.enfant {
  /* Pas de margin héritée — les enfants ont margin: 0 par défaut */
}
Enfant — a le background du parent mais pas le margin
Deuxième enfant — même comportement

4.3 Utiliser inherit

Démonstration : Forcer l'héritage avec inherit

.container-couleur {
  color: #7c3aed;     /* violet */
  font-family: 'Georgia', serif;
  font-size: 18px;
}

.link-purple a {
  color: inherit;     /* le lien hérite la couleur du parent au lieu du bleu par défaut */
}

Paragraphe violet dans le container

4.4 Utiliser initial

Démonstration : Réinitialiser avec initial

.parent-style {
  color: #dc2626;
  font-size: 24px;
  font-weight: bold;
  line-height: 2;
}

.enfant-reset {
  font-size: initial;   /* revient à la valeur initiale du spéculaire = medium (≈16px) */
  font-weight: initial; /* revient à normal */
  line-height: initial; /* revient à normal */
}

Parent : rouge, 24px, gras, interligne double

Enfant : taille et épaisseur réinitialisées, mais la couleur est héritée

4.5 Utiliser unset

Démonstration : unset se comporte différemment selon l'héritage

.parent-unset {
  color: #16a34a;           /* héritée */
  padding: 20px;            /* non héritée */
  background: #e2e8f0;      /* non héritée */
}

.enfant-unset {
  color: unset;             /* → inherit → prend la valeur du parent (vert) */
  padding: unset;           /* → initial → revient à 0 */
  background: unset;        /* → initial → revient à transparent */
}

Parent : vert, padding 20px, fond gris

Enfant : couleur héritée (vert), padding réinitialisé (0), fond transparent

4.6 Héritage dans un menu de navigation

Cas réel : Navigation avec héritage contrôlé

nav {
  font-family: 'Arial', sans-serif;  /* hérité par tous les enfants */
  font-size: 14px;                    /* hérité */
  color: #333;                        /* hérité */
}

nav a {
  color: inherit;        /* hérite du parent au lieu du bleu par défaut */
  text-decoration: none; /* pas hérité — à redéfinir */
  display: block;        /* pas hérité — à redéfinir */
  padding: 8px 16px;     /* pas hérité — à redéfinir */
}

nav a:hover {
  color: #2563eb;        /* surcharge locale */
}

4.7 Réinitialisation globale avec all: unset

Démonstration : Réinitialiser tous les styles hérités

/* Styles globaux */
body {
  font-family: 'Arial', sans-serif;
  font-size: 16px;
  color: #333;
  line-height: 1.5;
}

/* Composant isolé — reset complet */
.composant-isole {
  all: unset;  /* annule tous les styles hérités et non hérités */
  display: block;
  font-family: inherit;
  font-size: 14px;
  color: #666;
}

Texte stylé du parent

Composant isolé — styles réinitialisés avec all: unset

5. Erreurs fréquentes

Erreur 1 : Croire que toutes les propriétés s'héritent
/* FAUX raisonnement : "je définis margin sur le parent, ça s'appliquera aux enfants" */
.parent {
  margin: 20px;      /* NE s'hérite PAS */
  padding: 20px;     /* NE s'hérite PAS */
  border: 1px solid; /* NE s'hérite PAS */
}

/* Les enfants auront margin: 0, padding: 0, border: none par défaut */
Erreur 2 : Confondre initial et unset
/* initial = valeur du spéculaire CSS (par défaut dans le standard) */
/* unset = inherit si héritée, sinon initial */

/* Exemple avec color : */
.enfant-initial { color: initial; }  /* → blue (valeur initiale dans le spec) */
.enfant-unset { color: unset; }      /* → inherit → prend la valeur du parent */
Erreur 3 : Utiliser all: unset sans comprendre les conséquences
/* FAUX — all: unset supprime aussi display, box-sizing, etc. */
.composant {
  all: unset;
  /* display redevient inline, box-sizing redevient content-box,
     et TOUT le style est perdu ! */
}

/* CORRECT — cibler uniquement ce qu'on veut réinitialiser */
.composant {
  color: inherit;
  font-size: inherit;
  margin: 0;
  padding: 0;
}
Erreur 4 : Oublier que certains styles navigateur résistent à l'héritage
/* Les styles de user-agent pour <a>, <button>, <h1> à <h6>
   ont des valeurs par défaut qui peuvent surprendre */

/* Exemple : */
nav { color: red; }
nav a { /* Le lien reste bleu car le navigateur définit
           color pour <a> avec sa propre règle user-agent */ }

/* Solution : forcer l'héritage */
nav a { color: inherit; }

6. Bonnes pratiques

Règles d'or pour l'héritage :
  • Définir les propriétés textuelles au plus haut niveau possible (body ou conteneur racine) pour profiter de l'héritage.
  • Utiliser inherit intentionnellement quand tu veux qu'un lien ou un élément reprenne la couleur du parent.
  • Ne pas supposer que margin/padding/bordures s'héritent — les définir explicitement sur chaque élément.
  • Utiliser unset avec précaution — comprendre qu'il se comporte différemment selon que la propriété est héritée ou non.
  • Préférer all: unset avec une sélection précise pour isoler un composant.
  • Documenter l'origine des styles hérités quand le code devient complexe.
/* ✅ Bonne pratique : définir la base sur body */
body {
  font-family: 'Segoe UI', system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  color: #1e293b;
  background: #f8fafc;
}

/* Tous les descendants héritent de ces propriétés textuelles */

/* ✅ Bonne pratique : forcer inherit pour les liens dans un menu */
nav a {
  color: inherit;
}

7. Mini-défi

Exercice 1 : Héritage ou pas ?

Pour chaque propriété, indique si elle s'hérite ou non :

Propriété Héritée ?
colorOui
marginNon
font-sizeOui
borderNon
line-heightOui
paddingNon
text-alignOui
backgroundNon
font-familyOui
widthNon

Exercice 2 : Quelle valeur ?

Pour chaque scenario, indique la valeur calculée :

.parent {
  color: red;
  font-size: 20px;
  margin: 10px;
  padding: 15px;
}

.enfant {
  /* Aucune règle ciblant .enfant directement */
}

Réponses :

  • color : red (héritée)
  • font-size : 20px (héritée)
  • margin : 0 (non héritée → valeur initiale)
  • padding : 0 (non héritée → valeur initiale)

Exercice 3 : inherit vs unset

Quelle est la différence pour color et margin ?

.parent {
  color: blue;
  margin: 20px;
}

.enfant-inherit {
  color: inherit;
  margin: inherit;
}

.enfant-unset {
  color: unset;
  margin: unset;
}

Réponses :

  • .enfant-inherit : color = blue, margin = 20px
  • .enfant-unset : color = inherit → blue (color est héritée), margin = initial → 0 (margin n'est pas héritée)

Exercice 4 : Résoudre un problème d'héritage

Un développeur veut que les liens dans sa navigation aient la même couleur que le texte. Voici son code :

/* CSS */
.nav {
  color: white;
  background: #1e293b;
}

/* HTML */
<nav class="nav">
  <a href="#">Accueil</a>
  <a href="#">Services</a>
</nav>

Problème : Les liens restent bleus. Pourquoi ? Quelle est la solution ?

Réponse : Le navigateur a une règle user-agent qui définit color pour les <a>. La solution est .nav a { color: inherit; } pour forcer l'héritage.

8. Projet d'application

Projet : Système de thème avec héritage

Crée un fichier index.html et style.css avec un système de thème basé sur l'héritage :

Objectifs :

  • Définir les propriétés textuelles globales sur body (font, size, color, line-height)
  • Créer 3 conteneurs thématiques (clair, sombre, colorful) qui héritent de certains styles et en surchargent d'autres
  • Utiliser inherit pour les liens dans chaque thème
  • Utiliser initial ou unset pour isoler un composant
  • Montrer la différence entre hérité et non hérité avec des exemples visuels

Structure attendue :

<body>  ← styles globaux (hérités partout)
  <section class="theme-clair">
    <h2>Thème Clair</h2>
    <p>Texte</p>
    <a href="#">Lien</a>  ← color: inherit
  </section>
  <section class="theme-sombre">
    <h2>Thème Sombre</h2>
    <p>Texte</p>
    <a href="#">Lien</a>
  </section>
  <div class="composant-isole">
    <!-- composant avec all: unset ou initial -->
  </div>
</body>

9. Révision

Quiz rapide

  1. Qu'est-ce que l'héritage CSS ?
  2. La propriété margin s'hérite-t-elle ?
  3. La propriété color s'hérite-t-elle ?
  4. Quel mot-clé force l'héritage d'une propriété ?
  5. Quelle est la différence entre initial et unset ?
  6. Que fait all: unset sur une propriété héritée ?
  7. Pourquoi les liens <a> restent-ils bleus même quand on définit color sur le parent ?
  8. Comment forcer un lien à prendre la couleur de son parent ?
  9. Quel mot-clé revient aux styles du navigateur (user-agent) ?
  10. Donne 3 propriétés qui s'héritent et 3 qui ne s'héritent pas.
Réponses :
  1. C'est le mécanisme par lequel certaines propriétés se transmettent automatiquement du parent à ses enfants dans l'arbre DOM.
  2. Non — chaque élément doit définir son propre margin.
  3. Oui — la couleur du texte se transmet aux descendants.
  4. inherit
  5. initial remet à la valeur initiale du spéculaire CSS ; unset utilise inherit si la propriété est héritée, sinon initial.
  6. Il utilise inherit (car la propriété est héritée), donc prend la valeur du parent.
  7. Parce que le navigateur a sa propre règle user-agent qui définit color pour les <a>.
  8. a { color: inherit; }
  9. revert
  10. Héritées : color, font-size, line-height. Non héritées : margin, padding, border.