Skip to content
Torna al blog
Tutorial

PX vs REM vs EM: la guida completa alle unità CSS

px vs rem vs em: cosa significa ogni unità CSS, quando usare rem per l'accessibilità, la trappola degli em annidati e una guida online per proprietà.

12 min di lettura

PX vs REM vs EM: la guida completa alle unità CSS

Ecco la risposta breve su px vs rem vs em, prima di qualsiasi spiegazione. Usa rem per quasi tutto il dimensionamento (dimensioni dei font, padding, margini, gap, border-radius e breakpoint) perché scala con l’impostazione della dimensione del font scelta dal lettore nel browser. Usa px per le poche cose che non dovrebbero mai scalare, come un bordo di 1px o l’offset preciso di un’ombra. Usa em per il raro caso locale in cui un valore deve crescere insieme alla dimensione del font dell’elemento stesso, ad esempio il padding di un pulsante che segue il suo testo.

Questa regola copre il 90% delle decisioni. L’altro 10% è dove si annidano i problemi: la matematica del cumulo degli em che sorprende tutti la prima volta, il bug delle media query che rompe i layout in fase di zoom e i casi in cui px è in realtà la scelta più accessibile. Questa guida affronta tutti e tre i punti, con CSS eseguibile per ciascuno, più una tabella di riferimento per proprietà da tenere aperta mentre scrivi gli stili.

Cosa significano davvero px, rem ed em

Tre unità, tre punti di riferimento diversi.

px è un’unità assoluta. Un px è un pixel CSS e resta di quella dimensione qualunque cosa lo circondi. border: 1px solid è un pixel, punto e basta. Il rovescio della medaglia è che “assoluto” significa anche che ignora le preferenze dell’utente, sul perché questo conti torneremo più avanti.

rem è relativo alla dimensione del font dell’elemento root. Il root è <html> e i browser ne impostano la dimensione del font a 16px per impostazione predefinita. Quindi 1rem equivale a 16px in una configurazione standard, ovunque nella pagina, indipendentemente dall’annidamento. Quella coerenza è tutto il suo valore: un unico valore di riferimento, nessuna sorpresa.

em è relativo alla dimensione del font dell’elemento corrente (o del suo genitore, per le proprietà diverse da font-size). Poiché quel riferimento cambia mentre annidi gli elementi, i valori in em si spostano a seconda del contesto. Lo stesso 1.5em può risolversi in 24px in un punto e in 30px in un altro.

L’ancora da memorizzare è 16px = 1rem. Se non interiorizzi nient’altro, interiorizza questo. Quando devi convertire un valore specifico, il convertitore px in rem esegue la divisione rispetto alla base che scegli.

px vs rem vs em a colpo d’occhio

UnitàRelativa aScala con il font dell’utente?Uso tipicoComportamento nell’annidamento
pxNulla (assoluta)NoBordi, offset delle ombre, hairlineSempre della stessa dimensione
remFont del root <html>Dimensione font, spaziature, breakpointSempre della stessa dimensione
emFont dell’elemento correnteValori locali legati a un componenteSi cumula, può derivare

Le due colonne che risolvono la maggior parte delle discussioni sono “scala con il font dell’utente” e “comportamento nell’annidamento”. rem vince su entrambe: rispetta la preferenza del lettore e resta prevedibile. em condivide il primo vantaggio ma rinuncia al secondo.

Come si calcola ogni unità

La matematica è pura aritmetica. Ciò che manda in confusione è capire per quale numero dividere o moltiplicare.

rem usa la dimensione del font del root:

rem = px ÷ root-font-size

Con il root predefinito a 16px, 24px ÷ 16 = 1.5rem. Per tornare indietro, moltiplica: 1.5rem × 16 = 24px. Ogni rem nella pagina usa lo stesso 16 (o qualunque valore tu imposti per il root), ed è esattamente questo a rendere rem prevedibile.

em usa la dimensione del font dell’elemento corrente:

em = px ÷ current-element-font-size

Se il font-size di un elemento è 20px, allora 1em su quell’elemento è 20px, 0.5em è 10px e un padding di 1.5em è 30px. Cambia la dimensione del font dell’elemento e ogni valore em a esso collegato cambia di conseguenza. Quell’accoppiamento locale è il senso degli em, ed è anche la loro trappola.

La trappola del cumulo degli em

È la parte che i concorrenti sorvolano. Quando annidi elementi che usano tutti em per la dimensione del font, i valori si moltiplicano lungo l’albero. Ogni livello eredita la dimensione del font calcolata del proprio genitore e vi applica sopra il proprio fattore em.

.menu      { font-size: 1.2em; } /* il genitore è 16px → 19.2px */
.menu .item { font-size: 1.2em; } /* il genitore è 19.2px → 23.04px */
.menu .item .sub { font-size: 1.2em; } /* il genitore è 23.04px → 27.648px */

Ogni livello è il “120% del proprio genitore”, il che sembra innocuo. Ma poiché il genitore è già cresciuto, il terzo livello è 1.2 × 1.2 × 1.2 = 1.728em rispetto ai 16px originari, ovvero circa 27.6px, non i 19.2px che potresti aver letto guardando la regola in isolamento. Annida una lista dentro una lista dentro un componente e il testo si gonfia in un modo difficile da tracciare.

rem aggira del tutto il problema. 1.2rem è 19.2px sia che si trovi all’inizio del documento sia dodici livelli più in profondità, perché si misura sempre rispetto al root, mai rispetto al genitore. Quando un valore si risolve in una dimensione che non ti aspettavi, la prima domanda da porsi è se sia un em (relativo al genitore, si cumula) o un rem (relativo al root, stabile). Se stai facendo il debug di un rem sfuggito e vuoi vederne in fretta la dimensione in pixel, il convertitore rem in px lo risolve all’istante.

Quando usare rem

Scegli rem per impostazione predefinita. È l’unità giusta per dimensioni dei font, padding, margini, gap, border-radius e breakpoint delle media query, cioè qualsiasi cosa debba scalare quando un lettore regola la dimensione del testo.

Quest’ultima frase è l’argomento dell’accessibilità, e non è ipotetico. I sondaggi di WebAIM su screen reader e ipovisione rilevano con costanza che una quota consistente di utenti regola la dimensione del font predefinita del browser o del sistema operativo, molti ben oltre lo standard di 16px. Un layout dimensionato in rem onora quel cambiamento: porta il valore predefinito a 20px e ogni valore basato su rem cresce in proporzione. Un layout dimensionato in px lo ignora del tutto: il testo resta bloccato alla sua dimensione fissa, per quanto il lettore abbia bisogno di ingrandirlo.

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

h1   { font-size: 2rem;     } /* 32px, scala con la preferenza dell'utente */
p    { font-size: 1rem;     } /* 16px */
.card { padding: 1.5rem;    } /* 24px */
.card { border-radius: 0.5rem; } /* 8px */

Poiché ogni valore qui è ancorato allo stesso root, una singola modifica alla dimensione del font del root riscala l’intera interfaccia in proporzione. È anche ciò che mantiene coerente un design system: spaziature e tipografia si muovono insieme invece di allontanarsi a vicenda.

Il trucco del 62,5%

Esiste una scorciatoia molto diffusa per rendere banale l’aritmetica dei rem. Imposta la dimensione del font del root a 62.5%, ovvero 62.5% × 16px = 10px:

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

body {
  font-size: 1.6rem; /* ripristina un corpo del testo leggibile di 16px */
}

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

Con un root di 10px, il calcolo mentale si riduce a “dividi il valore in pixel per 10”: 24px → 2.4rem, 12px → 1.2rem. L’unico accorgimento è ripristinare una dimensione leggibile del corpo del testo con body { font-size: 1.6rem }, dato che una base di 10px lascia il testo predefinito troppo piccolo. Usare 62.5% come percentuale anziché 10px lo mantiene relativo, così un lettore che scala il valore predefinito del browser ottiene comunque una crescita proporzionale. Se adotti questa base, imposta a 10 la dimensione del font del root nel convertitore, in modo che corrisponda al tuo foglio di stile.

Quando usare em

Usa em quando vuoi che un valore scali con la dimensione del font dell’elemento stesso, non con quella del root. Il caso classico è un pulsante:

.btn {
  font-size: 1rem;      /* dimensionato rispetto al root */
  padding: 0.75em 1.5em; /* il padding segue il testo del pulsante */
}

.btn--large {
  font-size: 1.25rem;   /* una sola modifica ridimensiona tutto */
}

Poiché il padding è in em, il modificatore .btn--large ridimensiona il testo e il suo padding insieme da una singola dichiarazione, e il pulsante resta proporzionato a qualsiasi dimensione. La stessa logica vale per un’icona dimensionata in em perché si adatti alla riga di testo in cui si trova, o per una spaziatura tra le lettere che deve crescere con il font.

La strategia che funziona nella pratica è rem per lo scheletro globale, em per le proporzioni locali. Imposta la dimensione del font in rem così che risponda al root e alla preferenza dell’utente; imposta in em la manciata di valori che devono seguire quel particolare elemento. Tieni solo gli em lontani da tutto ciò che si annida in profondità, altrimenti la trappola del cumulo vista prima torna a insinuarsi.

Quando usare px

Alcuni valori non dovrebbero davvero scalare, e px è corretto per loro: un bordo hairline di 1px, l’offset preciso di un box-shadow, un focus ring di 2px. Sono dettagli di rendering, non contenuto. Un bordo che “scala” a 1.25px quando l’utente ingrandisce il testo non guadagna nulla e può apparire come una linea sfocata. px lo mantiene nitido.

.divider { border-bottom: 1px solid; }     /* dovrebbe restare 1px */
.card    { box-shadow: 0 2px 4px rgba(0,0,0,0.1); } /* offset fisso */
.input:focus { outline: 2px solid; }       /* focus ring nitido */

La sfumatura sorprendente: quando px è più accessibile

Ecco la parte controintuitiva che la maggior parte dei consigli “usa sempre rem” salta. La scelta accessibile non è “rem ovunque”, ma “scala ciò che deve scalare, fissa ciò che non deve”.

Un bordo di 1px è un dettaglio fisso. Costringerlo in rem così che cresca quando l’utente ingrandisce il testo non aiuta la leggibilità: rende solo sfocata una hairline. Per queste proprietà, px è la scelta più accessibile proprio perché resta fermo.

L’errore che si commette davvero è l’opposto: usare px per le cose che dovrebbero rispondere, come le dimensioni dei font e i breakpoint. È lì che px danneggia l’accessibilità. La regola, quindi, dipende dalla proprietà e non dall’unità. Chiediti se il valore è contenuto con cui il lettore interagisce (scalalo, rem) o un dettaglio di rendering fisso (fissalo, px). L’unità discende dalla risposta.

La trappola delle media query

Questa rompe layout reali e quasi nessuna guida ne avverte. I breakpoint delle media query scritti in px non rispondono allo zoom basato sulla dimensione del font del browser come ti aspetteresti.

Immagina un breakpoint a width: 600px dove una sidebar si comprime. Un utente con vista ridotta imposta il valore predefinito del browser a 24px per leggere comodamente. Il tuo contenuto ora ha bisogno di più spazio orizzontale, perché il testo più grande vuole riposizionarsi prima. Ma un breakpoint in px non sa che il testo è cresciuto; scatta sempre esattamente a 600px di viewport, quindi il layout cambia nel momento sbagliato e il contenuto si comprime o si sovrappone.

Confronta i due approcci:

/* breakpoint in px — ignora la preferenza di dimensione del font dell'utente */
@media (min-width: 600px) {
  .sidebar { display: block; }
}

/* breakpoint in em/rem — risponde alla dimensione del font dell'utente */
@media (min-width: 37.5em) {
  .sidebar { display: block; }
}

37.5em è 600px con il valore predefinito di 16px (600 ÷ 16 = 37.5). La differenza è comportamentale: quando l’utente raddoppia la dimensione del font predefinita, anche il breakpoint in em di fatto raddoppia, così il layout cambia a una larghezza del viewport proporzionale al testo, esattamente quando il contenuto lo richiede. Il breakpoint in px resta congelato.

Una particolarità da conoscere: nelle condizioni delle media query, em e rem si risolvono entrambi rispetto alla dimensione del font predefinita del browser, non a un eventuale override di html, quindi lì si comportano in modo identico. Entrambe le unità correggono il bug; px lo provoca.

La tabella decisionale per proprietà

Quando sei indeciso, questa tabella ti dà la risposta senza dover riderivare ogni volta la logica.

ProprietàUnità consigliataPerché
font-sizeremScala con la preferenza di dimensione del font dell’utente
padding / marginremLa spaziatura scala insieme al testo
borderpxLe hairline devono restare nitide e fisse
offset di box-shadowpxUn dettaglio di rendering preciso, non contenuto
border-radiusremMantiene la rotondità degli angoli proporzionata alla scala
media queryem / remI breakpoint devono rispondere allo zoom del font
width / max-widthrem (spesso ch per il testo)Larghezze di layout scalabili; ch limita la lunghezza della riga
line-heightsenza unitàUn moltiplicatore senza unità si eredita correttamente

La riga line-height merita una nota perché è un bug comune. Scrivi sempre line-height: 1.5, senza unità. Un valore senza unità è un moltiplicatore che ogni elemento calcola rispetto alla propria dimensione del font, così gli elementi annidati restano leggibili. Scrivi invece line-height: 1.5em o 24px e la lunghezza calcolata viene ereditata, il che significa che un figlio con una dimensione del font maggiore mantiene l’interlinea del genitore e il suo testo inizia a sovrapporsi. Senza unità si evita tutto il problema.

Convertire tra px e rem

L’aritmetica è abbastanza semplice da farla a mente una volta che tieni a mente l’ancora: 16px = 1rem. Dividi per 16 per passare a rem, moltiplica per 16 per tornare a px.

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

Se usi il trucco del 62,5%, la base diventa 10px e il calcolo è ancora più semplice: basta dividere o moltiplicare per 10, quindi 24px = 2.4rem. L’unica regola è convertire sempre rispetto alla base che il tuo foglio di stile imposta realmente.

Per tutto il resto (valori strani, un root personalizzato o la conversione in blocco di un’esportazione da Figma) lascia perdere il calcolo mentale e usa il convertitore px in rem o il convertitore rem in px. Entrambi permettono di impostare qualsiasi dimensione del font del root e di convertire in tempo reale in entrambe le direzioni. E se dopo stai sistemando un foglio di stile pieno di unità miste, il formattatore CSS normalizzerà spaziatura e indentazione al posto tuo.

Errori comuni

Alcuni schemi causano gran parte dei grattacapi legati alle unità:

Impostare la dimensione del font del root in px. Scrivere html { font-size: 16px } (invece di lasciare il valore predefinito o usare 100% / una percentuale) scavalca del tutto la preferenza di dimensione del font del browser dell’utente. I valori in rem si calcolano comunque rispetto a essa, ma il lettore non può più scalare l’intera pagina. Lascia il root al valore predefinito, oppure usa una percentuale.

Mescolare px e rem senza un sistema. Alcune dimensioni dei font in px, altre in rem, la spaziatura divisa tra le due: il risultato è un layout che scala in modo irregolare quando un utente regola il testo. Scegli rem come predefinito e riserva px alle eccezioni deliberate della tabella decisionale.

Usare em per la spaziatura globale. Em su contenitori annidati in profondità reintroduce la trappola del cumulo, così un padding in fondo all’albero si risolve in qualcosa che nessuno aveva previsto. Mantieni la spaziatura globale in rem; tieni gli em per valori locali, circoscritti al componente.

Dare un’unità a line-height. Come visto sopra, line-height: 24px o 1.5em viene ereditato come lunghezza calcolata e si rompe su elementi con dimensioni del font diverse. Usa sempre un moltiplicatore senza unità.

FAQ

rem è meglio di px?

Per la maggior parte del dimensionamento sì: rem è meglio di px perché scala con la preferenza di dimensione del font del browser dell’utente, che px ignora. Ma “meglio” dipende dalla proprietà: px è la scelta giusta per dettagli fissi come bordi di 1px e offset delle ombre che devono restare nitidi. Usa rem per il dimensionamento del contenuto, px per i dettagli di rendering.

Quanto vale 1rem in pixel?

1rem equivale alla dimensione del font del root in pixel, che è 16px per impostazione predefinita praticamente in tutti i browser. Quindi 1rem = 16px, 1.5rem = 24px e 2rem = 32px in una configurazione standard. Se un foglio di stile scavalca html { font-size }, ad esempio portandolo a 10px con il trucco del 62,5%, allora 1rem equivale a quel valore.

Per font-size dovrei usare rem o em?

Usa rem per font-size in quasi tutti i casi. Rem si misura rispetto al root, quindi resta prevedibile per quanto in profondità un elemento sia annidato. Em si misura rispetto alla dimensione del font del genitore, che si cumula lungo l’albero e fa gonfiare in modo imprevisto il testo annidato. Riserva em ai valori locali legati a un singolo componente.

Quando dovrei usare px invece di rem?

Usa px per i valori che non dovrebbero scalare con la dimensione del font dell’utente: bordi di 1px, offset precisi di box-shadow, contorni dei focus ring e altri dettagli di rendering fissi. Sono dettagli di design nitidi più che contenuto, quindi fissarli in px è la scelta più accessibile. Tutto ciò che riguarda il contenuto dovrebbe comunque usare rem.

Perché le media query si rompono quando uso px?

I breakpoint delle media query in px non rispondono allo zoom basato sulla dimensione del font del browser. Quando un utente ingrandisce il font predefinito, il suo contenuto ha bisogno di più spazio, ma un breakpoint in px scatta comunque alla stessa larghezza del viewport, così il layout cambia nel momento sbagliato. Usa breakpoint in em o rem, che scalano con la dimensione del font dell’utente.

Cos’è il trucco del 62,5% per font-size?

Il trucco del 62,5% imposta html { font-size: 62.5% }, rendendo la dimensione del font del root 10px (il 62,5% di 16). Con una base di 10px, la matematica dei rem diventa “dividi per 10”: 24px = 2.4rem, 12px = 1.2rem. Gli sviluppatori impostano poi body { font-size: 1.6rem } per ripristinare un corpo del testo leggibile di 16px.

Va bene mescolare px, rem ed em?

Sì, mescolare px, rem ed em è corretto quando ciascuno segue la proprietà a cui si adatta: rem per tipografia e spaziatura, px per i dettagli fissi, em per i valori locali circoscritti al componente. Ciò che crea problemi è mescolarli senza un sistema, ad esempio alcune dimensioni dei font in px e altre in rem. Scegli rem come predefinito e tratta px ed em come eccezioni deliberate.

Quale unità dovrei usare per padding e margin?

Usa rem per padding e margin, così la spaziatura scala insieme al testo quando l’utente regola la dimensione del font. Questo mantiene un layout proporzionato e accessibile. Riserva em al padding che deve seguire la dimensione del font dell’elemento stesso, come un pulsante il cui padding cresce con il suo testo, ed evita em sui contenitori annidati in profondità dove si cumula.

Tag: css rem em frontend accessibility responsive-design

Articoli correlati

Vedi tutti gli articoli