Ottimizza il caricamento e il rendering dei caratteri web

Ilya Grigorik
Ilya Grigorik

Un WebFont "completo" che include tutte le varianti stilistiche, che potresti non aver bisogno, oltre a tutti i glifi, che potrebbero non essere utilizzati, può facilmente comportare un download di diversi megabyte. In questo post scoprirai come ottimizzare il caricamento dei WebFonts in modo che i visitatori scarichino solo ciò che useranno.

Per risolvere il problema dei file di grandi dimensioni contenenti tutte le varianti, la regola CSS @font-face è progettata appositamente per consentirti di suddividere la famiglia di caratteri in una raccolta di risorse. Ad esempio, sottoinsiemi Unicode e varianti di stile distinte.

Grazie a queste dichiarazioni, il browser individua i sottoinsiemi e le varianti richiesti e scarica l'insieme minimo necessario per il rendering del testo, il che è molto pratico. Tuttavia, se non fai attenzione, puoi anche creare un collo di bottiglia delle prestazioni nel percorso di rendering critico e ritardare il rendering del testo.

Il comportamento predefinito

Il caricamento lento dei caratteri comporta un'importante implicazione nascosta che potrebbe ritardare il rendering del testo. Il browser deve costruire l'albero di rendering, che dipende dagli alberi DOM e CSSOM, prima di sapere quali risorse dei caratteri sono necessarie per eseguire il rendering del testo. Di conseguenza, le richieste dei caratteri vengono ritardate molto dopo le altre risorse critiche e il browser potrebbe non riuscire a eseguire il rendering del testo finché la risorsa non viene recuperata.

Percorso di rendering critico dei caratteri

  1. Il browser richiede il documento HTML.
  2. Il browser inizia ad analizzare la risposta HTML e a creare il DOM.
  3. Il browser rileva CSS, JS e altre risorse e invia le richieste.
  4. Il browser crea il CSSOM dopo aver ricevuto tutti i contenuti CSS e lo combina con l'albero DOM per creare l'albero di rendering.
    • Le richieste di caratteri vengono inviate dopo che la struttura di rendering indica quali varianti di carattere sono necessarie per eseguire il rendering del testo specificato nella pagina.
  5. Il browser esegue il layout e visualizza i contenuti sullo schermo.
    • Se il carattere non è ancora disponibile, il browser potrebbe non visualizzare i pixel di testo.
    • Una volta che il carattere è disponibile, il browser dipinge i pixel del testo.

La "corsa" tra la prima applicazione di colore dei contenuti della pagina, che può essere eseguita poco dopo la creazione dell'albero di rendering, e la richiesta della risorsa del carattere è ciò che crea il "problema del testo vuoto", in cui il browser potrebbe eseguire il rendering del layout della pagina, ma omettere qualsiasi testo.

Precaricando i WebFonts e utilizzando font-display per controllare il comportamento dei browser con i caratteri non disponibili, puoi evitare pagine vuote e variazioni del layout dovute al caricamento dei caratteri.

Precarica le risorse WebFont

Se è molto probabile che la tua pagina abbia bisogno di un WebFont specifico ospitato in un URL che conosci in anticipo, puoi usufruire della priorità delle risorse. L'utilizzo di <link rel="preload"> attiverà una richiesta del WebFont all'inizio del percorso di rendering critico, senza dover attendere la creazione del CSSOM.

Personalizzare il ritardo di rendering del testo

Sebbene il precaricamento aumenti le probabilità che un WebFont sia disponibile al momento del rendering dei contenuti di una pagina, non offre alcuna garanzia. Devi comunque considerare il comportamento dei browser durante il rendering del testo che utilizza un font-family non ancora disponibile.

Nel post Evitare il testo invisibile durante il caricamento dei caratteri puoi vedere che il comportamento predefinito del browser non è coerente. Tuttavia, puoi indicare ai browser moderni come vuoi che si comportino utilizzando font-display.

Supporto dei browser

  • Chrome: 60.
  • Edge: 79.
  • Firefox: 58.
  • Safari: 11.1.

Origine

Analogamente ai comportamenti di timeout dei caratteri esistenti implementati da alcuni browser, font-display suddivide la durata del download di un carattere in tre periodi principali:

  1. Il primo periodo è il periodo del blocco di caratteri. Durante questo periodo, se il carattere non viene caricato, qualsiasi elemento che tenta di utilizzarlo deve essere visualizzato con un carattere di riserva invisibile. Se il carattere viene caricato correttamente durante il periodo di blocco, viene utilizzato normalmente.
  2. Il periodo di sostituzione dei caratteri si verifica immediatamente dopo il periodo di blocco dei caratteri. Durante questo periodo, se il carattere non viene caricato, qualsiasi elemento che tenta di utilizzarlo deve essere visualizzato con un carattere di riserva. Se il carattere viene caricato correttamente durante il periodo di scambio, viene utilizzato normalmente.
  3. Il periodo di errore del carattere si verifica immediatamente dopo il periodo di scambio dei caratteri. Se il carattere non è ancora stato caricato all'inizio di questo periodo, viene contrassegnato come caricamento non riuscito, causando il normale fallback del carattere. In caso contrario, il carattere viene utilizzato normalmente.

Comprendere questi periodi significa che puoi utilizzare font-display per decidere come deve essere visualizzato il carattere a seconda che sia stato scaricato o meno e quando.

Per utilizzare la proprietà font-display, aggiungila alle regole @font-face:

@font-face {
  font-family: 'Awesome Font';
  font-style: normal;
  font-weight: 400;
  font-display: auto; /* or block, swap, fallback, optional */
  src: local('Awesome Font'),
       url('/fonts/awesome-l.woff2') format('woff2'), /* will be preloaded */
       url('/fonts/awesome-l.woff') format('woff'),
       url('/fonts/awesome-l.ttf') format('truetype'),
       url('/fonts/awesome-l.eot') format('embedded-opentype');
  unicode-range: U+000-5FF; /* Latin glyphs */
}

font-display attualmente supporta il seguente intervallo di valori:

  • auto
  • block
  • swap
  • fallback
  • optional

Per ulteriori informazioni sul precaricamento dei caratteri e sulla proprietà font-display, consulta i seguenti post:

L'API Font Loading

Se usati insieme, <link rel="preload"> e il CSS font-display ti offrono un ottimo controllo sul caricamento e sul rendering dei caratteri, senza aggiungere molto overhead. Tuttavia, se hai bisogno di personalizzazioni aggiuntive e sei disposto a sostenere il sovraccarico introdotto dall'esecuzione di JavaScript, esiste un'altra opzione.

L'API di caricamento dei caratteri fornisce un'interfaccia di scripting per definire e manipolare i caratteri CSS, monitorare l'avanzamento del download e sostituire il comportamento di caricamento lento predefinito. Ad esempio, se hai la certezza che è necessaria una determinata variante di carattere, puoi definirla e chiedere al browser di avviare un recupero immediato della risorsa del carattere:

Supporto dei browser

  • Chrome: 35.
  • Edge: 79.
  • Firefox: 41.
  • Safari: 10.

Origine

var font = new FontFace("Awesome Font", "url(/fonts/awesome.woff2)", {
  style: 'normal', unicodeRange: 'U+000-5FF', weight: '400'
});

// don't wait for the render tree, initiate an immediate fetch!
font.load().then(function() {
  // apply the font (which may re-render text and cause a page reflow)
  // after the font has finished downloading
  document.fonts.add(font);
  document.body.style.fontFamily = "Awesome Font, serif";

  // OR... by default the content is hidden,
  // and it's rendered after the font is available
  var content = document.getElementById("content");
  content.style.visibility = "visible";

  // OR... apply your own render strategy here...
});

Inoltre, poiché puoi controllare lo stato del carattere (tramite il metodo check()) e monitorare l'avanzamento del download, puoi anche definire una strategia personalizzata per il rendering del testo nelle tue pagine:

  • Puoi bloccare tutto il rendering del testo finché il carattere non è disponibile.
  • Puoi implementare un timeout personalizzato per ogni carattere.
  • Puoi utilizzare il carattere di riserva per sbloccare il rendering e inserire un nuovo stile che utilizzi il carattere preferito quando sarà disponibile.

Ma non è tutto: puoi anche combinare le strategie riportate sopra per diversi contenuti della pagina. Ad esempio, puoi ritardare il rendering del testo in alcune sezioni finché il carattere non è disponibile, utilizzare un carattere di riserva e poi eseguire nuovamente il rendering al termine del download del carattere.

La memorizzazione nella cache corretta è fondamentale

Le risorse dei caratteri sono in genere risorse statiche che non vengono aggiornate di frequente. Di conseguenza, sono ideali per una scadenza max-age lunga. Assicurati di specificare sia un'intestazione ETag condizionale sia un parametro Cache-Control ottimale per tutte le risorse dei caratteri.

Se la tua applicazione web utilizza un service worker, la pubblicazione delle risorse dei caratteri con una strategia cache-first è appropriata per la maggior parte dei casi d'uso.

Non dovresti memorizzare i caratteri utilizzando localStorage o IndexedDB; ciascuno di questi presenta i propri problemi di prestazioni. La cache HTTP del browser fornisce il meccanismo migliore e più affidabile per fornire le risorse dei caratteri al browser.

Elenco di controllo per il caricamento di WebFont

  • Personalizza il caricamento e il rendering dei caratteri utilizzando <link rel="preload">, font-display o l'API Font Loading: il comportamento di caricamento lento predefinito potrebbe comportare un ritardo nel rendering del testo. Queste funzionalità della piattaforma web ti consentono di eseguire l'override di questo comportamento per caratteri specifici e di specificare strategie di rendering e timeout personalizzate per diversi contenuti della pagina.
  • Specifica criteri di convalida e memorizzazione nella cache ottimali: i caratteri sono risorse statiche aggiornate raramente. Assicurati che i tuoi server forniscano un timestamp max-age di lunga durata e un token di convalida per consentire il riutilizzo efficiente dei caratteri tra pagine diverse. Se utilizzi un worker di servizio, è appropriata una strategia cache-first.

Test automatici per il comportamento di caricamento dei WebFont con Lighthouse

Lighthouse può aiutarti ad automatizzare il processo di verifica dell'applicazione delle best practice per l'ottimizzazione dei caratteri web.

I seguenti controlli possono aiutarti ad assicurarti che le tue pagine continuino a seguire le best practice per l'ottimizzazione dei caratteri web nel tempo: