Performance

font-display e il costo in CLS

font-display decide cosa mostra il browser mentre il webfont scarica: swap costa CLS, block nasconde il testo. I cinque valori e come ridurre lo scarto.

In sintesi

  • swap mostra subito il fallback e sposta il layout quando arriva il webfont.
  • block tiene il testo invisibile per circa 3 s: CLS basso, lettura peggiore.
  • size-adjust e le metriche di override riducono lo scarto fra fallback e webfont.

font-display decide cosa mostra il browser mentre il webfont scarica: swap mostra subito il fallback, optional rinuncia al font nelle reti lente, block nasconde il testo. Nessuno dei cinque valori è gratis in CLS.

I cinque valori, in tabella

ValoreBlocco del testoCosa vede il lettoreCosto
autoDecide il browserDipende dal browserImprevedibile
blockCirca 3 sNessun testoTesto invisibile, poi swap
swap0 msIl fallbackScarto di metrica
fallbackCirca 100 msIl fallback, poi il webfontScarto breve, poi stabile
optionalCirca 100 msIl fallbackNessuno sulle reti lente

I millisecondi sono quelli documentati su web.dev: circa 3 s di blocco per block, circa 100 ms per fallback e optional. Il numero che conta è la terza colonna: quando il webfont arriva dopo la finestra, il testo non cambia più.

Perché swap sposta il layout

Il fallback ha metriche diverse: altezza delle maiuscole, larghezza media dei caratteri, interlinea. Quando il webfont prende il posto del fallback la riga può cambiare altezza e ogni blocco sotto si sposta. Su un titolo grande lo spostamento si vede, su un paragrafo da 14 px produce un CLS piccolo ma reale.

Ridurre lo scarto, non solo il tempo

  • Nel @font-face del fallback dichiara size-adjust, ascent-override e descent-override: il testo occupa la stessa altezza prima e dopo.
  • Metti in preload il solo woff2 della piega, non tutti e 15: as="font", type="font/woff2", crossorigin.
  • Tieni i subset latin e latin-ext: gli altri subset sono byte che nessuno legge.
  • Usa font-display: optional sui pesi decorativi: se arrivano tardi, la pagina non si muove.

Misurare il foglio

grep -c "@font-face" public/fonts.css
grep -c "font-display" public/fonts.css
du -cb public/fonts/*.woff2 | tail -1

Il primo numero dice quanti blocchi dichiari, il secondo quanti dichiarano font-display: se i due valori differiscono, il browser applica auto a quelli che mancano. Il terzo è il peso su disco di tutti i file, 632.280 byte nel nostro caso.

La limitazione da dichiarare

font-display non elimina lo spostamento: decide quando avviene. Con block il CLS resta basso e il testo invisibile per 3 s, che peggiora la lettura e non la metrica. E l'auto-hosting riduce il rischio solo se i file arrivano dalla stessa origine e con cache lunga.

Dove continuare

Nel catalogo: componenti tipografici, gooey text morphing e testo animato. Le guide: font gratuiti per interfacce e tipografia fluida con clamp; l'articolo gemello su CLS e il confronto misurato librerie React 2026.

Domande frequenti

font-display è obbligatorio?

No. Senza dichiarazione il browser usa auto, che di norma si comporta come block per circa 3 secondi. Dichiararlo rende il comportamento esplicito.

swap o optional: quale scegliere?

swap se la famiglia è parte dell'identità e deve comparire; optional se il testo conta più del carattere e un secondo download vale una visita senza font.

font-display risolve il CLS dei font?

No, cambia quando il testo appare. Lo spostamento resta fra fallback e webfont: si riduce con size-adjust, ascent-override e un fallback di metrica simile.

Il preload serve su tutti i pesi?

No. Il preload toglie una richiesta dalla coda, quindi va sul solo file usato nella piega. Precaricare 15 file occupa la banda che serve a CSS e immagini.

I font self-hosted hanno meno CLS?

Non direttamente. Togliere la richiesta a un dominio terzo elimina DNS e connessione, quindi il font arriva prima e la finestra di swap si chiude prima.