Usare la tipografia avanzata con i caratteri locali

Scopri come l'API Local Font Access ti permette di accedere ai caratteri installati localmente e ottenere dettagli di basso livello sugli stessi

Caratteri sicuri per il web

Se ti occupi di sviluppo web da abbastanza tempo, potresti ricordare i cosiddetti font web safe. Questi caratteri sono noti per essere disponibili su quasi tutte le istanze dei sistemi operativi più utilizzati (ovvero Windows, macOS, le distribuzioni Linux più comuni, Android e iOS). All'inizio degli anni 2000, Microsoft ha anche lanciato un'iniziativa denominata Caratteri principali TrueType per il Web che forniva questi caratteri per il download senza costi con l'obiettivo che "ogni volta che visiti un sito web che le specificava, vedrai le pagine esattamente come previsto dal designer del sito". Sì, sono inclusi i siti impostati su Comic Sans MS. Ecco un classico stack di caratteri sicuri per il web (con il fallback finale di qualsiasi carattere sans-serif ) che potrebbe avere il seguente aspetto:

body {
  font-family: Helvetica, Arial, sans-serif;
}

Caratteri web

I tempi in cui i caratteri web sicuri erano davvero importanti sono lontani. Oggi abbiamo i caratteri web, alcuni dei quali sono persino caratteri variabili che possiamo modificare ulteriormente modificando i valori per i vari assi esposti. Puoi utilizzare i caratteri web dichiarando un blocco @font-face all'inizio del codice CSS, che specifica i file dei caratteri da scaricare:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: url('flamboyant.woff2');
}

Dopodiché, puoi utilizzare il carattere web personalizzato specificando font-family, come di consueto:

body {
  font-family: 'FlamboyantSansSerif';
}

Caratteri locali come vettore di impronte

La maggior parte dei caratteri web proviene, indovinate un po', dal web. Un fatto interessante, però, è che la proprietà src nella dichiarazione @font-face, oltre alla funzione url(), accetta anche una funzione local(). In questo modo, i caratteri personalizzati possono essere caricati localmente. Se l'utente ha installato FlamboyantSansSerif sul proprio sistema operativo, verrà utilizzata la copia locale anziché scaricata:

@font-face {
  font-family: 'FlamboyantSansSerif';
  src: local('FlamboyantSansSerif'), url('flamboyant.woff2');
}

Questo approccio fornisce un ottimo meccanismo di riserva che consente di risparmiare potenzialmente sulla larghezza di banda. Su internet, sfortunatamente, non possiamo avere cose carine. Il problema con la funzione local() è che può essere usata impropriamente per il fingerprinting del browser. A quanto pare, l'elenco dei caratteri installati da un utente può essere molto identificativo. Molte aziende hanno i propri caratteri aziendali installati sui laptop dei dipendenti. Ad esempio, Google ha un carattere aziendale chiamato Google Sans.

L'app Font Book di macOS che mostra un'anteprima del carattere Google Sans.
Carattere Google Sans installato sul laptop di un dipendente Google.

Un malintenzionato può provare a determinare per quale azienda lavora una persona verificando l'esistenza di un gran numero di caratteri aziendali noti come Google Sans. L'attaccante tenterà di eseguire il rendering del testo impostato su questi caratteri su una tela e di misurare i glifi. Se i glifi corrispondono alla forma nota del carattere aziendale, l'attaccante ha un hit. Se i glifi non corrispondono, l'aggressore sa che è stato utilizzato un carattere di sostituzione predefinito poiché il carattere aziendale non è stato installato. Per informazioni dettagliate su questo e su altri attacchi di fingerprinting del browser, leggi il report di sondaggio di Laperdix et al.

A parte i caratteri dell'azienda, anche solo l'elenco dei caratteri installati può essere un elemento di identificazione. La situazione con questo vettore di attacco è diventata così grave che di recente il team di WebKit ha deciso di "includere [nell'elenco dei caratteri disponibili] solo i caratteri web e i caratteri forniti con il sistema operativo, ma non i caratteri installati localmente dall'utente". Eccomi qui con un articolo su come concedere l'accesso ai caratteri locali.

API Local Font Access

L'inizio di questo articolo potrebbe averti messo di cattivo umore. Non possiamo davvero avere cose belle? Non preoccuparti. Pensiamo di potercela fare e forse non tutto è perduto. Ma prima, rispondi a una domanda che potresti porti.

Perché abbiamo bisogno dell'API Accesso ai caratteri locali se esistono i caratteri web?

È sempre stato difficile trovare strumenti di progettazione e grafica di qualità professionale sul web. Un ostacolo è stato l'impossibilità di accedere e utilizzare l'intera gamma di caratteri professionali costruiti e con indicatori che i designer hanno installato localmente. I caratteri web consentono alcuni casi d'uso per la pubblicazione, ma non consentono l'accesso programmatico alle forme dei glifi vettoriali e alle tabelle dei caratteri utilizzate dai rasterizzatori per il rendering dei contorni dei glifi. Analogamente, non è possibile accedere ai dati binari di un carattere web.

  • Gli strumenti di progettazione devono accedere ai byte dei caratteri per eseguire la propria implementazione del layout OpenType e consentire il collegamento a livelli inferiori, ad esempio per eseguire filtri vettoriali o trasformazioni sulle forme dei glifi.
  • Gli sviluppatori potrebbero avere stack di caratteri precedenti per le loro applicazioni che stanno portando sul web. Per utilizzare queste serie, di solito richiedono l'accesso diretto ai dati dei caratteri, cosa che i caratteri web non forniscono.
  • Alcuni caratteri potrebbero non essere concessi in licenza per la pubblicazione sul web. Ad esempio, Linotype ha una licenza per alcuni caratteri che include solo l'uso su computer.

L'API Accesso ai caratteri locali è un tentativo di risolvere questi problemi. È costituito da due parti:

  • Un'API di enumerazione dei caratteri, che consente agli utenti di concedere l'accesso all'insieme completo dei caratteri sistema disponibili.
  • Da ogni risultato dell'enumerazione, la possibilità di richiedere l'accesso ai contenitori SFNT a basso livello (orientato a byte) che include i dati completi dei caratteri.

Supporto browser

Supporto dei browser

  • Chrome: 103.
  • Edge: 103.
  • Firefox: non supportato.
  • Safari: non supportato.

Origine

Come utilizzare l'API Accesso ai caratteri locali

Rilevamento di funzionalità

Per verificare se l'API Local Font Access è supportata, utilizza:

if ('queryLocalFonts' in window) {
  // The Local Font Access API is supported
}

Elenco dei caratteri locali

Per ottenere un elenco dei caratteri installati localmente, devi chiamare window.queryLocalFonts(). La prima volta verrà attivata una richiesta di autorizzazione, che l'utente potrà approvare o negare. Se l'utente approva i caratteri locali per la query, il browser restituisce un array con dati dei caratteri su cui è possibile eseguire il loop. Ogni carattere è rappresentato come un oggetto FontData con le proprietà family (ad esempio "Comic Sans MS"), fullName (ad esempio "Comic Sans MS"), postscriptName (ad eg."ComicSansMS") e style (ad es. "Regular").

// Query for all available fonts and log metadata.
try {
  const availableFonts = await window.queryLocalFonts();
  for (const fontData of availableFonts) {
    console.log(fontData.postscriptName);
    console.log(fontData.fullName);
    console.log(fontData.family);
    console.log(fontData.style);
  }
} catch (err) {
  console.error(err.name, err.message);
}

Se ti interessa solo un sottoinsieme di caratteri, puoi anche filtrarli in base ai nomi PostScript aggiungendo un parametro postscriptNames.

const availableFonts = await window.queryLocalFonts({
  postscriptNames: ['Verdana', 'Verdana-Bold', 'Verdana-Italic'],
});

Accesso ai dati SFNT

L'accesso completo a SFNT è disponibile tramite il metodo blob() dell'oggetto FontData. SFNT è un formato file carattere che può contenere altri caratteri, come PostScript, TrueType, OpenType, Web Open Font Format (WOFF) e altri.

try {
  const availableFonts = await window.queryLocalFonts({
    postscriptNames: ['ComicSansMS'],
  });
  for (const fontData of availableFonts) {
    // `blob()` returns a Blob containing valid and complete
    // SFNT-wrapped font data.
    const sfnt = await fontData.blob();
    // Slice out only the bytes we need: the first 4 bytes are the SFNT
    // version info.
    // Spec: https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font
    const sfntVersion = await sfnt.slice(0, 4).text();

    let outlineFormat = 'UNKNOWN';
    switch (sfntVersion) {
      case '\x00\x01\x00\x00':
      case 'true':
      case 'typ1':
        outlineFormat = 'truetype';
        break;
      case 'OTTO':
        outlineFormat = 'cff';
        break;
    }
    console.log('Outline format:', outlineFormat);
  }
} catch (err) {
  console.error(err.name, err.message);
}

Demo

Puoi vedere l'API Local Font Access in azione nella demo di seguito. Assicurati di controllare anche il codice sorgente. La demo mostra un elemento personalizzato chiamato <font-select> che implementa un selettore di caratteri locale.

Considerazioni sulla privacy

L'autorizzazione "local-fonts" sembra fornire una superficie altamente rilevabile. Tuttavia, i browser sono liberi di restituire qualsiasi cosa. Ad esempio, i browser incentrati sull'anonimato possono scegliere di fornire solo un insieme di caratteri predefiniti integrati nel browser. Analogamente, i browser non sono tenuti a fornire i dati della tabella esattamente come appaiono sul disco.

Ove possibile, l'API Local Font Access è progettata per esporre solo le informazioni necessarie per abilitare i casi d'uso menzionati. Le API di sistema potrebbero produrre un elenco di caratteri installati non in ordine alfabetico o casuale, ma nell'ordine di installazione. Il ritorno esatto dell'elenco dei caratteri installati fornito da un'API di sistema di questo tipo può esporre dati aggiuntivi che potrebbero essere utilizzati per il fingerprinting e i casi d'uso che vogliamo abilitare non sono supportati dal mantenimento di questo ordinamento. Di conseguenza, questa API richiede che i dati restituiti vengano ordinati prima di essere restituiti.

Sicurezza e autorizzazioni

Il team di Chrome ha progettato e implementato l'API Local Font Access utilizzando i principi fondamentali definiti in Controllo dell'accesso a funzionalità potenti della piattaforma web, tra cui il controllo dell'utente, la trasparenza e l'ergonomia.

Controllo utente

L'accesso ai caratteri di un utente è completamente sotto il suo controllo e non sarà consentito a meno che non venga concessa l'autorizzazione"local-fonts", indicata nel registro delle autorizzazioni.

Trasparenza

La presenza o meno di un sito a cui è stato concesso l'accesso ai caratteri locali dell'utente sarà visibile nella scheda informativa del sito.

Persistenza delle autorizzazioni

L'autorizzazione "local-fonts" verrà mantenuta tra i ricaricamenti della pagina. Può essere revocata tramite il foglio Informazioni sul sito.

Feedback

Il team di Chrome vuole conoscere le tue esperienze con l'API Local Font Access.

Fornisci informazioni sul design dell'API

C'è qualcosa nell'API che non funziona come previsto? Oppure mancano metodi o proprietà di cui hai bisogno per implementare la tua idea? Hai domande o commenti sul modello di sicurezza? Invia una segnalazione relativa alle specifiche nel repository GitHub corrispondente o aggiungi il tuo parere a un problema esistente.

Segnalare un problema con l'implementazione

Hai trovato un bug nell'implementazione di Chrome? Oppure l'implementazione è diversa dalla specifica? Segnala un bug all'indirizzo new.crbug.com. Assicurati di includere il maggior numero di dettagli possibile, istruzioni semplici per la riproduzione e inserisci Blink>Storage>FontAccess nella casella Componenti. Glitch è ideale per condividere riproduzioni rapide e semplici.

Mostra il supporto per l'API

Hai intenzione di utilizzare l'API Accesso ai caratteri locali? Il tuo supporto pubblico aiuta il team di Chrome a dare la priorità alle funzionalità e mostra ad altri fornitori di browser quanto sia fondamentale supportarle.

Invia un tweet a @ChromiumDev utilizzando l'hashtag #LocalFontAccess e facci sapere dove e come lo stai utilizzando.

Ringraziamenti

La specifica dell'API Local Font Access è stata modificata da Emil A. Eklund, Alex Russell, Joshua Bell e Olivier Yiptong. Questo articolo è stato esaminato da Joe Medley, Dominik Röttsches e Olivier Yiptong. Immagine hero di Brett Jordan su Unsplash.