Niveau Niveau débutant

Le Reset CSS, une histoire d'héritage et de réinitialisation

Articlecss

Publié par le (34722 lectures)

héritage navigateur reset initial inherit revert unset normalize

Un Reset CSS c'est quoi ? Pour quoi ?

Les navigateurs web sont tenus d'appliquer des styles par défaut (User Agent Stylesheet) à chaque page HTML, sinon le document afficherait une page blanche (source : specifications CSS).

Chaque navigateur applique ses propres styles par défaut pouvant se révéler différents les uns des autres, sinon ce serait trop facile pour nous autres développeuses et développeurs !

Deux méthodes permettent de contourner ces différences d'affichages entre les navigateurs : le Reset CSS et le Normalize CSS.

Différence de rendu entre les navigateurs web (source)

Reset ou Normalize ?

Un "Reset CSS" (réinitialisation) est une technique qui consiste à repasser toutes les valeurs des propriétés CSS à leur état initial afin repartir de zéro et d'une base vierge avant d'appliquer nos propres styles.

Un "Normalize CSS" (harmonisation) consiste à appliquer des styles de base cohérents identiques sur chaque navigateur. Cette méthode corrige également les différences d'interprétation des spécifications et d'affichage sur l'ensemble des navigateurs et produit une base de travail suffisante (typographie, interlignages, marges, etc.)

Cela dépend bien évidemment de vos besoins, mais dans la plupart des projets il est suffisant d'appliquer une couche de Normalisation, car un Reset vous forcera à redéfinir toutes les propriétés une à une pour votre projet.

L'article (en anglais) Normalize CSS or CSS Reset?! de Elad Shechter résume bien cette dualité d'outils.

L'article (en anglais aussi) A tale of CSS Resets and Everything You Need to Know About Them. Revisited. de Margo Roi est extrêmement riche en informations sur l'évolution des techniques de Reset / Normalize, leur intérêt dans le détail et propose une liste très complète de l'ensemble des solutions existantes actuellement (Eric Meyer, Yahoo!, Normalize, Sanitize, Reboot, Remedy, etc.)

Comprendre et provoquer l'héritage des propriétés

Une propriété héritable est une propriété qui récupère automatiquement la valeur de son parent. C'est le cas par exemple des propriétés typographiques ou des listes (ex. font-size, color, list-style, etc.).

Une propriété non héritable adoptera par défaut la valeur initial telle que définie dans les Spécifications. Par exemple une bordure, une largeur de boîte ou une couleur de fond n'est pas transmise par héritage aux descendants. La majorité des propriétés CSS ne sont pas héritables.

Voici une liste des propriétés CSS héritables courantes :

  • color
  • cursor
  • direction
  • font-family
  • font-size
  • font-style
  • font-variant
  • font-weight
  • font
  • letter-spacing
  • line-height
  • list-style-image
  • list-style-position
  • list-style-type
  • list-style
  • text-align
  • text-indent
  • text-transform
  • visibility
  • white-space
  • word-spacing
Propriété héritée ou non ? (source)

Il est possible de forcer l'héritage d'une propriété en lui appliquant la valeur inherit. Elle prendra alors la valeur de la propriété du parent (c'est à dire son ancêtre direct).

Il est également possible de contrôler l'héritage de toutes les propriétés grâce à la propriété raccourcie all afin d'appliquer la valeur indiquée sur toutes les propriétés (source : MDN : Héritage).

Cibler toutes les propriétés via all

La propriété all est un super-raccourci de toutes les propriétés appliquables à un élément, ce qui lui permet d'hériter ou de réinitialiser toutes les valeurs à la fois.

Les valeurs possibles sont inherit, initial, unset et revert.

Exemple :

.parent {
  display: grid;
  margin: 2rem;
  color: hotpink;
}
.enfant {
  all: inherit; 
}

Dans cet exemple, all cible toutes les propriétés de .enfant et inherit les rend héritables, donc cela est équivalent au code suivant (pour les propriétés concernées) :

.enfant {
  display: grid;
  margin: 2rem;
  color: hotpink;
}

Appliquer les valeurs par défaut via initial

La valeur initial appliquée à une propriété lui confère sa valeur par défaut telle que prévue par les Spécifications CSS.

Exemple :

.parent {
  display: grid;
  margin: 2rem;
  color: hotpink;
}
.enfant {
  all: initial; 
}

Cet exemple est équivalent au code suivant (pour les propriétés concernées) :

.enfant {
  display: inline;
  margin: 0;
  color: canvastext;
}

Ce résultat peut surprendre dans la mesure où l'on s'attend généralement à la valeur block pour la propriété display (surtout si l'enfant est un élément tel que <div> ou <p>) ou black pour la propriété color, or il n'en est rien.

Il faut comprendre que toutes les propriétés CSS ont une valeur initiale définie dans les Spécifications (exemple display vaut inline). Puis elle est parfois écrasée par le navigateur au cas par cas selon les éléments (exemple div {display: block})

Quelques exemples de valeurs initial surprenantes :

  • display: initial; vaut inline
  • max-width: initial; vaut none
  • width: initial; vaut auto
  • position: initial; vaut static
  • cursor: initial; vaut auto
  • appearance: initial; vaut none
  • color: initial; vaut canvastext (valeur récente, adaptée aux modes utilisateur Dark et Light).

Réinitialiser ou hériter via unset

La valeur unset appliquée à une propriété lui confère la valeur du parent si la propriété peut être héritée ou la valeur initiale dans le cas contraire.

Exemple :

.parent {
  display: grid;
  margin: 2rem;
  color: hotpink;
}
.enfant {
  all: unset; 
}

Cet exemple est équivalent au code suivant (pour les propriétés concernées) :

.enfant {
  display: inline;
  margin: 0;
  color: hotpink;
}

Dans cet exemple, display et margin ne sont pas héritables donc leur valeur est calculée à initial, mais la couleur, héritable, est transmise.

Quelques exemples de valeurs unset :

  • max-width: unset; : non héritable donc unset vaut initial qui vaut none
  • width: unset; : non héritable donc unset vaut initial qui vaut auto
  • position: unset; : non héritable donc unset vaut initial qui vaut static
  • font-size: unset; : héritable donc récupère la valeur du parent
  • color: unset; : héritable donc récupère la valeur du parent (ici hotpink)
Tweet de Benjamin de Cock illustrant l'intérêt de la valeur `unset` appliquée sur un bouton

Récupérer la valeur du navigateur via revert

La valeur revert récupère la valeur appliquée par l'Agent Utilisateur.
S'il n'y en a pas, revert devient unset (qui lui-même vaut inherit ou initial selon le cas 🤯)

Exemple :

.parent {
  display: grid;
  margin: 2rem;
  color: hotpink;
}
.enfant {
  all: revert; 
}

Cet exemple est équivalent au code suivant (pour les propriétés concernées) :

.enfant {
  display: block;
  margin: 0;
  color: hotpink;
}

Dans cet exemple, display vaudra block puisque c'est la valeur attribuée par le navigateur sur l'élément <div>. Le navigateur n'applique pas de valeurs spécifiques au propriétés margin et color donc elles deviendront respectivement initial et inherit.

Quelques exemples de valeurs revert selon l'élément appliqué :

  • div {display: revert} vaut block
  • p {display: revert} vaut block
  • span {display: revert} vaut inline
  • td {display: revert} vaut table-cell
  • input {display: revert} vaut inline-block

Ces valeurs conférées par les navigateurs (User Agent Stylesheet) présentent parfois quelques différences selon les moteurs de rendu.

L'inspecteur d'élément de votre navigateur (clic droit > Inspecter) permet lui aussi d'afficher les valeurs CSS qu'il applique.

Vers le Reset / Normalize parfait ?

L'ensemble des propriétés et valeurs décrites au sein de cet article (all, inherit, initial, unset et revert) offre une très large panoplie de possibilités de réinitialisation en CSS lorsque cela vous est nécessaire.

Un Reset CSS proche de la perfection ressemblerait à ces deux simples lignes :

* {
  all: unset;
  display: revert;
}

Ces deux lignes résument à elles seules les consignes suivantes :

  • Toutes les propriétés appliquables à tous les éléments doivent être remises à zéro, sauf pour les propriétés héritables qui sont conservées, cela évite de devoir tout re-styler notamment pour les propriétés typographiques.
  • Concernant la propriété display, nous souhaitons que la navigateur continue d'appliquer ses valeurs préférées (donc block, inline, etc. selon l'élément).

Si la perfection existait, nous serions en présence du Reset ultime. Mais dans la vraie vie il y a aussi des images, des vidéos, des iframes, des tableaux, des SVG, etc.

Voilà pourquoi je ne saurais que vous conseiller de vous intéresser au projet "The New CSS Reset" maintenu sur Github par l'excellent Ahmad Shadeed et qui apporte les quelques affinages nécessaires.

The New CSS Reset

Et vous, quelle est votre position par rapport à ces problématiques d'héritages, de cascades et de reset CSS ?

Avez-vous des solutions à tout faire que vous nous recommanderiez ?

Commentaires

C'est assez sympa comme reset ce "New CSS reset", mais si on a des soucis de compatibilité avec de vieux navigateurs, ça casse vite vu les sélecteurs utilisés :)

D'expérience, je dirais que c'est vraiment selon le besoin : pour du site simple avec peu de contraintes de compatibilité, du reset/normalize léger et simple, ça suffit amplement. Je mixe même les deux dans mes projets simples.

Sur des apps destinées à des parcs plus conséquents, c'est en général plus riche et surtout plus étendu. Genre j'ai remarqué que -webkit-appearance: none faisait planter la vocalization sur des inputs de type radio/checkboxes... des joyeusetés dans le genre ! Donc là on doit être beaucoup plus prudent dans les resets. Exemple : https://github.com/ProtonMail/WebClients/blob/main/packages/styles/scss/base/_reset.scss

Commenter

Vous devez être inscrit et identifié pour utiliser cette fonction.

Connectez-vous (déjà inscrit)

Oubli de mot de passe ? Pas de panique, on va le retrouver

Pas encore inscrit ? C'est très simple et gratuit.