rem ou em en une démo imbriquée
rem est relatif à la taille de police racine (l'élément <html>, 16px par défaut). em est relatif à la taille de police courante, c'est-à-dire, pour font-size, celle du parent. Imbriquez trois fois la même classe et la différence apparaît :
Les tailles affichées sont celles calculées par le navigateur. Chaque 1.25em multiplie celle de son parent : 20px, puis 25px, puis 31,25px. Chaque 1.25rem ne regarde que la racine : 20px, 20px, 20px. Cette multiplication explique pourquoi les tailles de police en em deviennent incontrôlables dans les listes et menus imbriqués, et pourquoi la plupart des sites définissent les tailles de police en rem.
À quoi chaque unité est relative
| Unité | Relative à | 1 unité par défaut |
|---|---|---|
px | rien (un pixel CSS) | 1px |
rem | la taille de police de l'élément racine (html) | 16px |
em | la taille de police de l'élément ; pour font-size elle-même, celle du parent | 16px au premier niveau |
% | dépend de la propriété (voir ci-dessous) | |
vw / vh | 1 % de la largeur / hauteur du viewport | |
dvh, svh, lvh | 1 % de la hauteur dynamique, petite ou grande du viewport | |
vmin / vmax | 1 % du plus petit / plus grand côté du viewport | |
ch | la largeur du « 0 » dans la police courante | environ un demi-em |
ex | la hauteur d'x de la police courante | environ un demi-em |
Un pixel CSS n'est pas un pixel physique : sur un téléphone à écran 3x, 1px fait 3 pixels physiques de large. Il garde à peu près la même taille visuelle d'un écran à l'autre, c'est pourquoi px convient toujours aux bordures et aux ombres.
em pour des espacements qui suivent le texte
em ne sert pas qu'aux tailles de police. Sur padding, margin, width ou border-radius, il signifie « fois la taille de police de cet élément ». Une seule classe de bouton fonctionne alors à toutes les tailles :
Le padding de chaque bouton vaut la moitié de sa taille de police verticalement et une taille de police horizontalement : les trois ressemblent au même bouton en trois tailles. Avec un padding en px, il faudrait une règle de padding séparée pour chaque taille.
Notez que les boutons n'héritent pas de la taille de police de la page par défaut (les navigateurs donnent leur propre taille aux contrôles de formulaire) : le bouton du milieu fait donc ici 13,33px dans Chrome, pas 16px. Ajoutez font: inherit aux boutons et aux champs quand vous voulez qu'ils suivent la page.
Les pourcentages : cela dépend de la propriété
% n'a pas de sens unique. Chaque propriété indique de quoi il s'agit :
| Propriété | % est relatif à |
|---|---|
width, max-width, left, right | la largeur du parent (bloc conteneur) |
height, top, bottom | la hauteur du parent, et seulement si le parent a une hauteur définie |
padding, margin (les quatre côtés) | la largeur du parent |
font-size | la taille de police du parent (150% = 1.5em) |
line-height | la taille de police de l'élément lui-même |
transform: translate() | la taille de l'élément lui-même |
width: 50% vaut 200px, la moitié du parent. padding-top: 5% vaut 20px : 5 % de la largeur du parent, pas de sa hauteur. Et height: 50% ne fait rien, car le parent n'a pas de hauteur définie : l'enfant n'est donc pas plus haut que son texte plus ce padding. La page width et height détaille cette règle.
vw, vh et la barre d'adresse mobile
1vw vaut 1 % de la largeur du viewport et 1vh 1 % de sa hauteur. Ils sont utiles pour les sections plein écran et pour les tailles fluides (souvent dans clamp()). Sur téléphone, vh a un piège : la barre d'adresse du navigateur apparaît et disparaît pendant le défilement, et 100vh correspond à la hauteur sans la barre, donc une bannière en height: 100vh est coupée en bas quand la barre est affichée. Les unités plus récentes règlent ce problème :
| Unité | Hauteur utilisée |
|---|---|
100vh | le grand viewport (barres masquées) sur la plupart des navigateurs mobiles |
100svh | le petit viewport (barres affichées) : tient toujours |
100lvh | le grand viewport, explicitement |
100dvh | le viewport dynamique : change quand les barres bougent |
.hero {
min-height: 100vh; /* fallback for older browsers */
min-height: 100svh; /* fits the screen even with the address bar visible */
}
vw a aussi son piège : 100vw inclut la largeur d'une barre de défilement verticale quand celle-ci prend de la place (comme sous Windows), donc width: 100vw peut être plus large que la page et ajouter une barre de défilement horizontale. Utilisez width: 100% pour « toute la largeur du parent ».
ch pour une longueur de ligne lisible
ch est la largeur du caractère « 0 » : max-width: 65ch limite donc un paragraphe à environ 65 caractères par ligne, une longueur de lecture confortable, quelle que soit la taille de police :
Quelle unité utiliser
| Pour | Utilisez | Pourquoi |
|---|---|---|
| Les tailles de police | rem | Cohérent partout, respecte le réglage de taille de police du lecteur |
| Le padding et les espaces dans les composants | rem ou em | em quand il doit grandir avec le texte du composant |
| Bordures, filets, ombres | px | Doivent rester fins à toute taille de police |
| Largeurs de mise en page | %, fr, max-width en rem ou ch | Suivent le conteneur, limitent la longueur de ligne |
| Sections plein écran | svh / dvh (avec vh en secours) | Gèrent les barres d'adresse mobiles |
| Typographie fluide | clamp() mêlant rem et vw | Grandit avec l'écran, dans des limites |
Pourquoi rem respecte les lecteurs et px non
Les navigateurs ont un réglage de taille de police par défaut, utilisé par les personnes qui ont besoin d'un texte plus grand. Il change la taille de police racine, donc tout ce qui est en rem et en em grandit avec lui. Un font-size: 14px reste à 14px quel que soit le choix du lecteur. Le zoom du navigateur agrandit aussi les px, mais c'est sur le réglage de taille de police que beaucoup de lecteurs comptent. C'est la principale raison de définir les tailles de police en rem.
Certains sites définissent html { font-size: 62.5%; } pour que 1rem vaille 10px et que les calculs soient plus simples. Cela respecte toujours le réglage du lecteur (62,5 % de ce qu'il a choisi), mais pensez à définir une font-size lisible sur body, sinon chaque élément sans taille propre affiche un texte de 10px.
Erreurs courantes
- Des tailles de police en
emdans des éléments imbriqués. Elles se multiplient à chaque niveau. Utilisezrempour les tailles de police. - Un
height: 50%qui ne fait rien. Le parent doit avoir une hauteur définie pour qu'une hauteur en pourcentage fonctionne. - Croire que
padding-top: 10%suit la hauteur du parent. Les pourcentages de padding et de margin verticaux utilisent la largeur du parent. width: 100vwqui crée une barre de défilement horizontale. Il inclut la barre de défilement. Utilisez100%.height: 100vhcoupé sur téléphone. Utilisez100svhou100dvh.- Définir
html { font-size: 12px }. Une valeur en px sur la racine écrase le réglage de taille de police du lecteur pour toute la page. Ne touchez pas à la racine ou utilisez un pourcentage.
Questions fréquentes
Quelle est la différence entre rem et em ?
rem est relatif à la taille de police de l'élément racine (<html>), donc 1.5rem a la même taille partout sur la page. em est relatif à la taille de police de l'élément lui-même (pour font-size, celle du parent), donc il se multiplie quand les éléments sont imbriqués.
Combien de pixels vaut 1rem ?
16px par défaut, car les navigateurs règlent la taille de police racine à 16px. Si l'utilisateur augmente la taille de police par défaut dans les réglages de son navigateur, ou si vous définissez html { font-size: ... }, 1rem change avec elle.
Faut-il utiliser rem ou px pour la taille de police ?
Utilisez rem pour les tailles de police. Il respecte la taille de police par défaut choisie par le lecteur dans son navigateur, ce que px ignore. Le zoom du navigateur agrandit les deux, mais tous les lecteurs n'utilisent pas le zoom.
Quand utiliser em plutôt que rem ?
Utilisez em pour les espacements qui doivent suivre le texte de l'élément lui-même, comme le padding d'un bouton ou la taille d'une icône à côté d'un texte. La même classe rend alors bien à n'importe quelle taille de police. Utilisez rem pour les tailles de police et les espacements à l'échelle de la page, pour que rien ne se multiplie.
Quelle est la différence entre 100vh et 100dvh ?
Sur les navigateurs mobiles, 100vh correspond à la hauteur avec la barre d'adresse masquée, donc une section de 100vh est plus haute que l'écran visible tant que la barre est affichée. 100dvh (hauteur dynamique du viewport) suit la barre quand elle apparaît et disparaît, et 100svh correspond toujours à la plus petite hauteur.