Usare la tipografia avanzata con i caratteri locali

Scopri come l'API Accesso ai caratteri locali ti consente di accedere ai caratteri installati localmente dall'utente e di ottenere dettagli di basso livello su di essi

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 persino lanciato un'iniziativa chiamata Caratteri di base 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 li specifica, 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

Sono finiti i tempi in cui i caratteri sicuri per il web contavano davvero. 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 CSS, che specifica i file dei caratteri da scaricare:

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

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

body {
  font-family: 'FlamboyantSansSerif';
}

Caratteri locali come vettore di impronta

La maggior parte dei caratteri web proviene, indovinate un po', dal web. Un fatto interessante, tuttavia, è che la proprietà src nella dichiarazione @font-face, a parte la 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é scaricarla:

@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. Purtroppo, su internet non possiamo avere cose belle. Il problema con la funzione local() è che può essere usata impropriamente per il fingerprinting del browser. È emerso che l'elenco di caratteri installati da un utente può essere molto identificabile. 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'utente malintenzionato potrebbe tentare di eseguire il rendering del testo impostato in questi caratteri su una tela e misurare i glifi. Se i glifi corrispondono alla forma nota del carattere aziendale, l'attaccante ha un hit. Se i glifi non corrispondono, l'autore dell'attacco sa che è stato utilizzato un carattere sostitutivo predefinito perché il carattere aziendale non era 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". ed eccomi, con un articolo sulla concessione dell'accesso ai caratteri locali.)

L'API Local Fonts Access

L'inizio di questo articolo potrebbe averti messo in cattiva umore. Non possiamo davvero avere cose belle? No. 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. Allo stesso modo, 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 legacy per le loro applicazioni che stanno introducendo 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'utilizzo su computer.

L'API Accesso ai caratteri locali è un tentativo di risolvere questi problemi. Si compone di 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 un accesso al container SFNT di basso livello (orientato ai 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 delle caratteristiche

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à attivato un prompt di autorizzazione, che l'utente può approvare o rifiutare. Se l'utente approva la query sui caratteri locali, il browser restituirà un array con i dati dei caratteri su cui puoi eseguire un ciclo. 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 di file di caratteri che può contenere altri caratteri, ad esempio 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

Sembra che l'autorizzazione "local-fonts" fornisca una superficie facilmente identificabile. 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 nella sezione Controllare l'accesso a funzionalità avanzate della piattaforma web, tra cui controllo dell'utente, trasparenza ed 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 dalle specifiche? 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 è la soluzione perfetta per condividere riproduzioni in modo facile e veloce.

Mostra il supporto per l'API

Intendi utilizzare l'API Local Font Access? Il supporto pubblico aiuta il team di Chrome a dare la priorità alle funzionalità e mostra agli 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 letto da Joe Medley, Dominik Röttsches e Olivier Yiptong. Immagine hero di Brett Jordan su Unsplash.