rem vs em in una demo annidata
rem è relativo alla dimensione del font della radice (l'elemento <html>, 16px di default). em è relativo alla dimensione del font corrente, che per font-size significa quella del genitore. Annida la stessa classe tre volte e la differenza si vede:
Le dimensioni stampate sono quelle calcolate dal browser. Ogni 1.25em moltiplica quella del genitore: 20px, poi 25px, poi 31.25px. Ogni 1.25rem guarda solo la radice: 20px, 20px, 20px. È questo effetto moltiplicativo il motivo per cui le dimensioni del font in em sfuggono di mano in liste e menu annidati, e per cui la maggior parte dei siti imposta le dimensioni del font in rem.
A cosa è relativa ogni unità
| Unità | Relativa a | 1 unità di default |
|---|---|---|
px | niente (un pixel CSS) | 1px |
rem | la dimensione del font dell'elemento radice (html) | 16px |
em | la dimensione del font dell'elemento; per font-size stesso, quella del genitore | 16px al livello più alto |
% | dipende dalla proprietà (vedi sotto) | |
vw / vh | l'1% della larghezza / altezza del viewport | |
dvh, svh, lvh | l'1% dell'altezza dinamica, piccola o grande del viewport | |
vmin / vmax | l'1% del lato minore / maggiore del viewport | |
ch | la larghezza dello "0" nel font corrente | circa mezzo em |
ex | l'altezza della x nel font corrente | circa mezzo em |
Un pixel CSS non è un pixel del dispositivo: su un telefono con schermo 3x, 1px è largo 3 pixel del dispositivo. Mantiene più o meno la stessa dimensione visiva su tutti gli schermi, ed è per questo che px va ancora bene per bordi e ombre.
em per spaziature che scalano con il testo
em non serve solo per le dimensioni del font. Su padding, margin, width o border-radius significa "volte la dimensione del font di questo elemento". Così una sola classe di pulsante funziona a qualsiasi dimensione:
Il padding di ogni pulsante è metà della sua dimensione del font in verticale e una dimensione del font in orizzontale, quindi i tre sembrano lo stesso pulsante in tre taglie. Con un padding in px ti servirebbe una regola di padding diversa per ogni taglia.
Nota che i pulsanti non ereditano di default la dimensione del font della pagina (i browser danno ai controlli dei form la loro), quindi qui il pulsante centrale misura 13.33px in Chrome, non 16px. Aggiungi font: inherit a pulsanti e input quando vuoi che corrispondano alla pagina.
Percentuali: dipende dalla proprietà
% non ha un significato unico. Ogni proprietà definisce di cosa è una percentuale:
| Proprietà | % è relativo a |
|---|---|
width, max-width, left, right | la larghezza del genitore (del blocco contenitore) |
height, top, bottom | l'altezza del genitore, e solo se il genitore ha un'altezza impostata |
padding, margin (tutti e quattro i lati) | la larghezza del genitore |
font-size | la dimensione del font del genitore (150% = 1.5em) |
line-height | la dimensione del font dell'elemento stesso |
transform: translate() | la dimensione dell'elemento stesso |
width: 50% sono 200px, metà del genitore. padding-top: 5% sono 20px: il 5% della larghezza del genitore, non della sua altezza. E height: 50% non fa nulla, perché il genitore non ha un'altezza impostata, quindi il figlio è alto solo quanto il suo testo più quel padding. La pagina su width e height spiega questa regola nel dettaglio.
vw, vh e la barra degli indirizzi su mobile
1vw è l'1% della larghezza del viewport e 1vh l'1% della sua altezza. Sono utili per sezioni a schermo intero e per dimensioni fluide (spesso dentro clamp()). Sui telefoni, vh ha un tranello: la barra degli indirizzi del browser entra ed esce mentre scorri, e 100vh è l'altezza senza la barra, quindi un hero con height: 100vh resta tagliato in basso quando la barra è visibile. Le unità più recenti risolvono il problema:
| Unità | Altezza usata |
|---|---|
100vh | il viewport grande (barre nascoste) nella maggior parte dei browser mobili |
100svh | il viewport piccolo (barre visibili): ci sta sempre |
100lvh | il viewport grande, in modo esplicito |
100dvh | il viewport dinamico: cambia mentre le barre si muovono |
.hero {
min-height: 100vh; /* fallback for older browsers */
min-height: 100svh; /* fits the screen even with the address bar visible */
}
Anche vw ha il suo tranello: 100vw include la larghezza di una barra di scorrimento verticale quando questa occupa spazio (come su Windows), quindi width: 100vw può essere più largo della pagina e aggiungere una barra di scorrimento orizzontale. Usa width: 100% per "tutta la larghezza del genitore".
ch per una lunghezza di riga leggibile
ch è la larghezza del carattere "0", quindi max-width: 65ch limita un paragrafo a circa 65 caratteri per riga, una lunghezza di lettura comoda, con qualsiasi dimensione del font:
Quale unità usare
| Per | Usa | Perché |
|---|---|---|
| Dimensioni del font | rem | Coerente ovunque, rispetta l'impostazione della dimensione del font del lettore |
| Padding e gap nei componenti | rem o em | em quando deve crescere con il testo del componente stesso |
| Bordi, linee sottili, ombre | px | Devono restare sottili con qualsiasi dimensione del font |
| Larghezze di layout | %, fr, max-width in rem o ch | Seguono il contenitore, limitano la lunghezza della riga |
| Sezioni a schermo intero | svh / dvh (con vh come fallback) | Gestiscono le barre degli indirizzi su mobile |
| Tipografia fluida | clamp() che combina rem e vw | Cresce con lo schermo entro dei limiti |
Perché rem rispetta i lettori e px no
I browser hanno un'impostazione per la dimensione del font predefinita, usata da chi ha bisogno di un testo più grande. Cambia la dimensione del font della radice, quindi tutto ciò che è in rem e em cresce di conseguenza. Un font-size: 14px resta 14px qualunque cosa abbia scelto il lettore. Anche lo zoom del browser scala i px, ma l'impostazione della dimensione del font è quella su cui contano molti lettori. È il motivo principale per impostare le dimensioni del font in rem.
Alcuni siti impostano html { font-size: 62.5%; } così 1rem vale 10px e i calcoli sono più facili. Rispetta comunque l'impostazione del lettore (il 62.5% di quello che ha scelto), ma ricordati di impostare un font-size leggibile su body, altrimenti ogni elemento senza una dimensione propria mostra testo da 10px.
Errori comuni
- Dimensioni del font in
emin elementi annidati. Si moltiplicano a ogni livello. Usaremper le dimensioni del font. - Un
height: 50%che non fa nulla. Il genitore ha bisogno di un'altezza impostata perché un'altezza in percentuale funzioni. - Aspettarsi che
padding-top: 10%segua l'altezza del genitore. Le percentuali di padding e margin verticali usano la larghezza del genitore. width: 100vwche causa una barra di scorrimento orizzontale. Include la barra di scorrimento. Usa100%.- Un
height: 100vhtagliato sui telefoni. Usa100svho100dvh. - Impostare
html { font-size: 12px }. Un valore in px sulla radice sovrascrive l'impostazione della dimensione del font del lettore in tutta la pagina. Lascia stare la radice o usa una percentuale.
Domande frequenti
Che differenza c'è tra rem ed em?
rem è relativo alla dimensione del font dell'elemento radice (<html>), quindi 1.5rem ha la stessa dimensione in tutta la pagina. em è relativo alla dimensione del font dell'elemento stesso (per font-size, a quella del genitore), quindi si moltiplica quando gli elementi sono annidati.
Quanti pixel è 1rem?
16px di default, perché i browser impostano la dimensione del font della radice a 16px. Se l'utente aumenta la dimensione del font predefinita nelle impostazioni del browser, o se imposti html { font-size: ... }, 1rem cambia di conseguenza.
Meglio rem o px per la dimensione del font?
Usa rem per le dimensioni del font. Rispetta l'impostazione della dimensione del font predefinita del lettore nel browser, che px ignora. Lo zoom del browser scala entrambi, ma non tutti i lettori usano lo zoom.
Quando usare em invece di rem?
Usa em per le spaziature che devono scalare con il testo dell'elemento stesso, come il padding di un pulsante o la dimensione di un'icona accanto al testo. Così la stessa classe si vede bene con qualsiasi dimensione del font. Usa rem per le dimensioni del font e le spaziature a livello di pagina, così niente si moltiplica.
Che differenza c'è tra 100vh e 100dvh?
Nei browser mobili, 100vh è l'altezza con la barra degli indirizzi nascosta, quindi una sezione di 100vh è più alta dello schermo visibile mentre la barra è mostrata. 100dvh (altezza dinamica del viewport) segue la barra quando compare e scompare, e 100svh è sempre l'altezza più piccola.