Skip to content
Retour au blog
Tutoriels

PX vs REM vs EM : le guide complet des unités CSS

px vs rem vs em : ce que signifie chaque unité CSS, quand utiliser rem pour l'accessibilité, le piège du cumul des em et un aide-mémoire par propriété.

12 min de lecture

PX vs REM vs EM : le guide complet des unités CSS

Voici la réponse courte à la question px vs rem vs em. Utilisez rem pour la quasi-totalité des dimensions (tailles de police, marges intérieures, marges extérieures, espacements, rayons de bordure et points de rupture), parce que cette unité s’adapte au réglage de taille de police choisi dans le navigateur du lecteur. Utilisez px pour les quelques éléments qui ne doivent jamais varier, comme une bordure de 1px ou un décalage d’ombre précis. Utilisez em pour le cas local rare où une valeur doit croître avec la taille de police de l’élément lui-même, par exemple le rembourrage d’un bouton qui suit la taille de son texte.

Cette règle couvre 90 % des décisions. Les 10 % restants concentrent les vrais ennuis : le calcul de cumul des em qui surprend tout le monde la première fois, le bug de media query qui casse les mises en page au zoom, et les cas où px est en réalité le choix le plus accessible. Ce guide passe en revue ces trois points, avec du CSS exécutable pour chacun, plus un aide-mémoire par propriété à garder ouvert pendant que vous écrivez vos styles.

Ce que px, rem et em signifient vraiment

Trois unités, trois points de référence différents. Toute la distinction tient là.

px est une unité absolue. Un px vaut un pixel CSS, et il garde cette taille quel que soit son environnement. border: 1px solid fait un pixel, point final. Le hic, c’est qu’« absolu » signifie aussi qu’il ignore les préférences de l’utilisateur ; nous verrons plus loin pourquoi cela compte.

rem est relatif à la taille de police de l’élément racine. La racine est <html>, et les navigateurs fixent sa taille de police à 16px par défaut. Donc 1rem vaut 16px dans une configuration standard, partout sur la page, quelle que soit l’imbrication. C’est précisément cette constance qui fait son intérêt : une seule valeur d’ancrage, aucune surprise.

em est relatif à la taille de police de l’élément courant (ou de son parent, pour les propriétés autres que font-size). Comme cette référence change à mesure que vous imbriquez les éléments, les valeurs en em varient selon le contexte. Le même 1.5em peut se résoudre en 24px à un endroit et en 30px à un autre.

L’ancrage à retenir est 16px = 1rem. Si vous ne retenez rien d’autre, retenez cela. Quand vous devez convertir une valeur précise, le convertisseur px en rem effectue la division par rapport à la base de votre choix.

px vs rem vs em en un coup d’œil

UnitéRelative àS’adapte à la taille de police de l’utilisateur ?Usage typiqueComportement en imbrication
pxRien (absolu)NonBordures, décalages d’ombre, filets finsToujours la même taille
remTaille de police de la racine <html>OuiTaille de police, espacement, points de ruptureToujours la même taille
emTaille de police de l’élément courantOuiValeurs locales liées à un composantSe cumule, peut dériver

Les deux colonnes qui tranchent la plupart des débats sont « s’adapte à la taille de police de l’utilisateur » et « comportement en imbrication ». rem l’emporte sur les deux : il respecte la préférence du lecteur et reste prévisible. em partage le premier avantage mais sacrifie le second.

Comment chaque unité se calcule

Le calcul relève de l’arithmétique élémentaire. Ce qui piège, c’est de savoir par quel nombre diviser ou multiplier.

rem utilise la taille de police de la racine :

rem = px ÷ taille-de-police-racine

À la racine par défaut de 16px, 24px ÷ 16 = 1.5rem. Pour revenir en arrière, multipliez : 1.5rem × 16 = 24px. Chaque rem de la page utilise ce même 16 (ou la valeur que vous donnez à la racine), et c’est exactement pour cela que rem est prévisible.

em utilise la taille de police de l’élément courant lui-même :

em = px ÷ taille-de-police-de-l-élément-courant

Si la font-size d’un élément est 20px, alors 1em sur cet élément vaut 20px, 0.5em vaut 10px, et un rembourrage de 1.5em vaut 30px. Changez la taille de police de l’élément et chaque valeur en em qui lui est rattachée change avec elle. Ce couplage local est tout l’intérêt de l’em, et aussi son piège.

Le piège du cumul des em

C’est la partie que les concurrents survolent. Quand vous imbriquez des éléments qui utilisent tous em pour leur taille de police, les valeurs se multiplient en descendant l’arbre. Chaque niveau hérite de la taille de police calculée de son parent et applique son propre facteur em par-dessus.

.menu      { font-size: 1.2em; } /* le parent fait 16px → 19.2px */
.menu .item { font-size: 1.2em; } /* le parent fait 19.2px → 23.04px */
.menu .item .sub { font-size: 1.2em; } /* le parent fait 23.04px → 27.648px */

Chaque niveau vaut « 120 % de son parent », ce qui paraît anodin. Mais comme le parent a déjà grandi, le troisième niveau vaut 1.2 × 1.2 × 1.2 = 1.728em par rapport au 16px d’origine, soit environ 27.6px, et non les 19.2px que vous auriez pu lire sur la règle prise isolément. Imbriquez une liste dans une liste dans un composant et le texte enfle d’une manière difficile à retracer.

rem esquive complètement ce problème. 1.2rem vaut 19.2px qu’il se trouve en haut du document ou douze niveaux plus bas, parce qu’il se mesure toujours par rapport à la racine, jamais au parent. Quand une valeur se résout en une taille inattendue, la première question à poser est de savoir si c’est de l’em (relatif au parent, se cumule) ou du rem (relatif à la racine, stable). Si vous déboguez un rem isolé et que vous voulez voir sa taille en pixels rapidement, le convertisseur rem en px le résout instantanément.

Quand utiliser rem

Choisissez rem par défaut. C’est la bonne unité pour les tailles de police, les marges intérieures, les marges extérieures, les espacements, les rayons de bordure et les points de rupture des media queries, bref tout ce qui doit s’adapter quand un lecteur ajuste la taille de son texte.

Cette dernière proposition est l’argument d’accessibilité, et il n’est pas hypothétique. Les enquêtes de WebAIM auprès des utilisateurs de lecteurs d’écran et des personnes malvoyantes montrent qu’une large part des utilisateurs ajustent la taille de police par défaut de leur navigateur ou de leur système, beaucoup bien au-dessus du 16px standard. Une mise en page dimensionnée en rem suit ce changement : passez la valeur par défaut à 20px et chaque valeur fondée sur rem grandit proportionnellement. Une mise en page dimensionnée en px l’ignore complètement : le texte reste figé à sa taille codée en dur, peu importe à quel point le lecteur a besoin qu’il soit plus grand.

:root {
  font-size: 16px; /* 1rem = 16px */
}

h1   { font-size: 2rem;     } /* 32px, s'adapte à la préférence de l'utilisateur */
p    { font-size: 1rem;     } /* 16px */
.card { padding: 1.5rem;    } /* 24px */
.card { border-radius: 0.5rem; } /* 8px */

Comme chaque valeur ici est ancrée à la même racine, un seul changement de la taille de police racine redimensionne toute l’interface en proportion. C’est aussi ce qui maintient la cohérence d’un design system : l’espacement et la typographie évoluent ensemble au lieu de se désynchroniser.

L’astuce des 62,5 %

Il existe un raccourci populaire pour rendre l’arithmétique des rem triviale. Réglez la taille de police racine à 62.5%, soit 62.5% × 16px = 10px :

html {
  font-size: 62.5%; /* maintenant 1rem = 10px */
}

body {
  font-size: 1.6rem; /* rétablit un corps de texte lisible à 16px */
}

h1 { font-size: 2.4rem; } /* 24px */
p  { font-size: 1.6rem; } /* 16px */

Avec une racine à 10px, le calcul mental se réduit à « divisez la valeur en pixels par 10 » : 24px → 2.4rem, 12px → 1.2rem. Le seul détail est de rétablir une taille de corps lisible avec body { font-size: 1.6rem }, car une base brute de 10px rend le texte par défaut bien trop petit. Utiliser 62.5% comme pourcentage plutôt que 10px garde la valeur relative, de sorte qu’un lecteur qui agrandit la valeur par défaut de son navigateur garde une croissance proportionnelle. Si vous adoptez cette base, réglez la taille de police racine du convertisseur sur 10 pour qu’elle corresponde à votre feuille de style.

Quand utiliser em

Utilisez em lorsque vous voulez qu’une valeur s’adapte à la taille de police propre de l’élément, et non à celle de la racine. Le cas classique est le bouton :

.btn {
  font-size: 1rem;      /* dimensionné par rapport à la racine */
  padding: 0.75em 1.5em; /* le rembourrage suit le texte du bouton */
}

.btn--large {
  font-size: 1.25rem;   /* un seul changement redimensionne tout */
}

Comme le rembourrage est en em, le modificateur .btn--large redimensionne le texte et son rembourrage ensemble à partir d’une seule déclaration, et le bouton reste proportionné à n’importe quelle taille. La même logique s’applique à une icône dimensionnée en em pour qu’elle s’accorde à la ligne de texte où elle se trouve, ou à un interlettrage qui doit grandir avec la police.

La stratégie qui fonctionne en pratique est rem pour le squelette global, em pour les proportions locales. Réglez la taille de police en rem pour qu’elle réponde à la racine et à la préférence de l’utilisateur ; réglez la poignée de valeurs qui doivent suivre cet élément en em. Gardez simplement em à l’écart de tout ce qui s’imbrique profondément, sous peine de voir le piège du cumul vu plus haut réapparaître.

Quand utiliser px

Certaines valeurs ne doivent vraiment pas varier, et px convient pour elles : une bordure filet de 1px, un décalage de box-shadow précis, un anneau de focus de 2px. Ce sont des détails de rendu, pas du contenu. Une bordure qui « s’adapterait » à 1.25px quand l’utilisateur agrandit son texte n’y gagne rien et peut s’afficher comme une ligne floue. px la garde nette.

.divider { border-bottom: 1px solid; }     /* doit rester à 1px */
.card    { box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* décalage fixe */
.input:focus { outline: 2px solid; }       /* anneau de focus net */

La nuance surprenante : quand px est plus accessible

Voici la partie contre-intuitive que la plupart des conseils « toujours utiliser rem » passent sous silence. Le choix accessible n’est pas « rem partout ». C’est « faites varier ce qui doit varier, fixez ce qui ne doit pas ».

Une bordure de 1px est un détail fixe. La forcer en rem pour qu’elle grandisse quand l’utilisateur agrandit le texte n’aide pas la lisibilité ; cela ne fait que rendre un filet flou. Pour ces propriétés, px est le choix le plus accessible précisément parce qu’il reste en place.

L’erreur que les gens commettent réellement est l’inverse : utiliser px pour les éléments qui devraient répondre, comme les tailles de police et les points de rupture. C’est là que px nuit à l’accessibilité. La règle ne porte donc pas sur l’unité, mais sur la propriété. Demandez-vous si la valeur est du contenu avec lequel le lecteur interagit (faites-la varier : rem) ou un détail de rendu fixe (épinglez-la : px). L’unité découle de la réponse.

Le piège des media queries

Celui-ci casse de vraies mises en page et presque aucun guide n’en avertit. Les points de rupture de media queries écrits en px ne répondent pas au zoom de taille de police du navigateur comme vous l’espéreriez.

Imaginez un point de rupture à width: 600px où une barre latérale se replie. Un utilisateur malvoyant règle la valeur par défaut de son navigateur à 24px pour lire confortablement. Votre contenu a désormais besoin de plus de place horizontale, car le texte plus grand veut se réagencer plus tôt. Mais un point de rupture en px ignore que le texte a grandi ; il bascule toujours exactement à 600px de la fenêtre, si bien que la mise en page change au mauvais moment et que le contenu se retrouve à l’étroit ou se chevauche.

Comparez les deux approches :

/* point de rupture en px — ignore la préférence de taille de police de l'utilisateur */
@media (min-width: 600px) {
  .sidebar { display: block; }
}

/* point de rupture en em/rem — répond à la taille de police de l'utilisateur */
@media (min-width: 37.5em) {
  .sidebar { display: block; }
}

37.5em vaut 600px à la valeur par défaut de 16px (600 ÷ 16 = 37.5). La différence est comportementale : quand l’utilisateur double sa taille de police par défaut, le point de rupture en em double aussi de fait, donc la mise en page bascule à une largeur de fenêtre proportionnelle au texte, exactement quand le contenu en a besoin. Le point de rupture en px reste figé.

Une bizarrerie à connaître : dans les conditions de media query, em et rem se résolvent tous deux par rapport à la taille de police par défaut du navigateur, et non à une surcharge sur html, donc ils se comportent de façon identique à cet endroit. L’une ou l’autre unité corrige le bug ; px le provoque.

Le tableau de décision par propriété

Quand vous hésitez, ce tableau tranche. C’est le moyen le plus rapide de décider sans refaire le raisonnement à chaque fois.

PropriétéUnité recommandéePourquoi
font-sizeremS’adapte à la préférence de taille de police de l’utilisateur
padding / marginremL’espacement varie de concert avec le texte
borderpxLes filets doivent rester nets et fixes
décalage de box-shadowpxUn détail de rendu précis, pas du contenu
border-radiusremGarde l’arrondi des coins proportionnel à l’échelle
media queryem / remLes points de rupture doivent répondre au zoom de taille de police
width / max-widthrem (souvent ch pour le texte)Largeurs de mise en page adaptables ; ch limite la longueur de ligne
line-heightsans unitéUn multiplicateur sans unité s’hérite correctement

La ligne line-height mérite une note car c’est un bug fréquent. Écrivez toujours line-height: 1.5, sans unité. Une valeur sans unité est un multiplicateur que chaque élément calcule par rapport à sa propre taille de police, de sorte que les éléments imbriqués restent lisibles. Écrivez plutôt line-height: 1.5em ou 24px et c’est la longueur calculée qui est héritée, ce qui veut dire qu’un enfant avec une plus grande taille de police conserve la hauteur de ligne du parent et que son texte commence à se chevaucher. Le sans-unité évite tout le problème.

Convertir entre px et rem

L’arithmétique est assez simple pour la faire de tête une fois que vous tenez l’ancrage : 16px = 1rem. Divisez par 16 pour aller vers rem, multipliez par 16 pour revenir vers px.

pxrem (base 16px)
8px0.5rem
12px0.75rem
16px1rem
24px1.5rem
32px2rem

Si vous utilisez l’astuce des 62,5 %, la base devient 10px et le calcul est encore plus simple : divisez ou multipliez juste par 10, donc 24px = 2.4rem. La seule règle est de toujours convertir par rapport à la base que votre feuille de style fixe réellement.

Pour tout le reste (valeurs inhabituelles, racine personnalisée, ou conversion en lot d’un export Figma), laissez de côté le calcul mental et utilisez le convertisseur px en rem ou le convertisseur rem en px. Tous deux vous laissent fixer n’importe quelle taille de police racine et convertir dans les deux sens en temps réel. Et si vous remettez ensuite de l’ordre dans une feuille de style truffée d’unités mélangées, le formateur CSS normalisera l’espacement et l’indentation à votre place.

Erreurs courantes

Quelques tournures causent l’essentiel des soucis liés aux unités :

Régler la taille de police racine en px. Écrire html { font-size: 16px } (au lieu de laisser la valeur par défaut ou d’utiliser 100% / un pourcentage) outrepasse purement et simplement la préférence de taille de police du navigateur de l’utilisateur. Les valeurs en rem se calculent toujours par rapport à elle, mais le lecteur ne peut plus mettre toute la page à l’échelle. Laissez la racine à sa valeur par défaut, ou utilisez un pourcentage.

Mélanger px et rem sans système. Certaines tailles de police en px, d’autres en rem, l’espacement réparti entre les deux : il en résulte une mise en page qui se met à l’échelle de façon inégale quand un utilisateur ajuste son texte. Choisissez rem par défaut et réservez px aux exceptions délibérées du tableau de décision.

Utiliser em pour l’espacement global. Em sur des conteneurs largement imbriqués réintroduit le piège du cumul, si bien qu’un padding enfoui dans l’arbre se résout en une valeur que personne n’a voulue. Gardez l’espacement global en rem ; réservez em aux valeurs locales, à l’échelle d’un composant.

Donner une unité à line-height. Comme vu plus haut, line-height: 24px ou 1.5em est hérité comme une longueur calculée et casse sur les éléments aux tailles de police différentes. Utilisez toujours un multiplicateur sans unité.

FAQ

rem est-il meilleur que px ?

Pour la plupart des dimensions, oui : rem est meilleur que px parce qu’il s’adapte à la préférence de taille de police du navigateur de l’utilisateur, ce que px ignore. Mais « meilleur » dépend de la propriété : px est le bon choix pour les détails fixes comme les bordures de 1px et les décalages d’ombre qui doivent rester nets. Utilisez rem pour le dimensionnement du contenu, px pour les détails de rendu.

Combien font 1rem en pixels ?

1rem vaut la taille de police racine en pixels, soit 16px par défaut dans pratiquement tous les navigateurs. Donc 1rem = 16px, 1.5rem = 24px et 2rem = 32px dans une configuration standard. Si une feuille de style surcharge html { font-size } (par exemple à 10px via l’astuce des 62,5 %), alors 1rem vaut cette valeur à la place.

Dois-je utiliser rem ou em pour font-size ?

Utilisez rem pour font-size dans presque tous les cas. Rem se mesure par rapport à la racine, donc il reste prévisible quelle que soit la profondeur d’imbrication d’un élément. Em se mesure par rapport à la taille de police du parent, qui se cumule en descendant l’arbre et fait enfler le texte imbriqué de façon inattendue. Réservez em aux valeurs locales liées à un seul composant.

Quand devrais-je utiliser px plutôt que rem ?

Utilisez px pour les valeurs qui ne doivent pas varier avec la taille de police de l’utilisateur : bordures de 1px, décalages de box-shadow précis, contours d’anneaux de focus et autres détails de rendu fixes. Ce sont des détails de design nets plutôt que du contenu, donc les épingler en px est le choix le plus accessible. Tout ce qui relève du contenu devrait toujours utiliser rem.

Pourquoi les media queries cassent-elles quand j’utilise px ?

Les points de rupture de media queries en px ne répondent pas au zoom de taille de police du navigateur. Quand un utilisateur agrandit sa police par défaut, son contenu a besoin de plus de place, mais un point de rupture en px bascule toujours à la même largeur de fenêtre, et la mise en page change donc au mauvais moment. Utilisez des points de rupture en em ou rem, qui s’adaptent à la taille de police de l’utilisateur.

Qu’est-ce que l’astuce des 62,5 % pour la taille de police ?

L’astuce des 62,5 % règle html { font-size: 62.5% }, ce qui fait passer la taille de police racine à 10px (62,5 % de 16). Avec une base de 10px, le calcul des rem devient « diviser par 10 » : 24px = 2.4rem, 12px = 1.2rem. Les développeurs règlent ensuite body { font-size: 1.6rem } pour rétablir un corps de texte lisible à 16px.

Peut-on mélanger px, rem et em ?

Oui, mélanger px, rem et em est correct quand chacun suit la propriété qui lui convient : rem pour la typographie et l’espacement, px pour les détails fixes, em pour les valeurs locales à l’échelle d’un composant. Ce qui pose problème, c’est de les mélanger sans système, par exemple certaines tailles de police en px et d’autres en rem. Choisissez rem par défaut et traitez px et em comme des exceptions délibérées.

Quelle unité utiliser pour padding et margin ?

Utilisez rem pour padding et margin afin que l’espacement varie de concert avec le texte quand l’utilisateur ajuste sa taille de police. Cela garde une mise en page proportionnée et accessible. Réservez em au rembourrage qui doit suivre la taille de police propre d’un élément, comme un bouton dont le rembourrage grandit avec son texte, et évitez em sur les conteneurs profondément imbriqués où il se cumule.

Tags: css rem em frontend accessibility responsive-design

Articles connexes

Voir tous les articles