Diario · Nota 002 · Tipografia
Dieci lingue, tre file di font
Quando porti un sito in dieci lingue, il budget dei font è il primo a saltare. Qui ha retto. I caratteri cirillici e arabi hanno imposto un altro costo, che abbiamo mostrato senza nasconderlo.
Fondatore, BLN Global · · 6 min di lettura
Risposta breve
Con gli stessi tre font serviti da Google Fonts, una pagina turca scaricherebbe 6 file per 250 KB da due origini esterne. Dal nostro server ne scarica 3 per 165 KB, da un'unica origine. Il risparmio nasce soprattutto dal blocco degli assi inutilizzati, non dai sottoinsiemi. Per i caratteri cirillici e arabi abbiamo dovuto scegliere famiglie separate. In arabo, alcuni simboli arrivano dal font di riserva.
La tipografia del sito usava tre famiglie: Archivo per i titoli, Instrument Sans per il testo, Martian Mono per numeri ed etichette. Tutti e tre sono font variabili. Con cinque lingue filava tutto. Passando a dieci, sono cresciuti insieme due problemi: byte scaricati e copertura degli alfabeti.
Cosa confrontiamo con cosa
Confrontare i file TTF grezzi con i WOFF2 pubblicati sarebbe scorretto. Gran parte della differenza dipende dalla compressione, non dal sottoinsieme. Il confronto utile è con l’alternativa reale: quanti dati avresti scaricato usando le stesse tre famiglie da Google Fonts.
Non scarica tutti e nove i file. Il browser unicode-range controlla il campo e carica solo i sottoinsiemi necessari. Per una pagina in turco significa latin + latin-ext per ogni famiglia:
latin 88.0 KB <- latin-ext 83.8 KB <- vietnamese 33.6 KB latin 29.2 KB <- latin-ext 10.8 KB <- latin 23.0 KB <- latin-ext 15.5 KB <- cyrillic 10.3 KB cyrillic-ext 3.1 KB La pagina in turco scarica: 250 KB (6 file)
Il peso dei font nella pagina turca
archivo.woff2 + instrument.woff2 + martian.woff2 la dimensione reale dei file su disco.Oltre ai byte, sono arrivati altri due vantaggi: sei richieste sono diventate tre e sono spariti del tutto gli handshake DNS + TLS verso due origini esterne. Come abbiamo chiuso il problema delle risorse che bloccavano il primo paint nella nota sugli ultimi 18 punti lo spieghiamo.
Tre trappole
Uno: nel subset latin-ext mancano le lettere latine di base
Al primo tentativo abbiamo scaricato il file latin-ext di Google Fonts e ne abbiamo creato un sottoinsieme. Il risultato conteneva 130 glifi, ma nessuna cifra. Il motivo è semplice: latin-ext non contiene tutto latin. extra è un subset, non un alfabeto completo. La strada giusta è scaricare il font variabile completo dal repository google/fonts ed estrarre tu il subset.
Due: se non fissi gli assi inutilizzati, il file diventa cinque volte più grande
Ogni asse di un font variabile pesa sul file. Nel design usiamo solo peso e larghezza. Se non blocchi gli altri assi ai valori predefiniti, i loro dati restano nel file.
completo = {a.axisTag: a.defaultValue for a in t['fvar'].axes if a.axisTag not in assi} completo.update(assi) # Gli assi diversi da wght/wdth restano sul valore predefinito, # altrimenti il file pesa cinque volte tanto
Tre: gvar si carica in lazy
dopo aver bloccato l’asse con fontTools, se provi a fare subito il subset KeyError: space si estrae. Il motivo è il lazy loading dei dati dei glifi variabili (gvar): dopo il pinning, l’oggetto in memoria sembra coerente, ma il subsetter non riesce a leggerlo. La soluzione fa un giro largo, ma sta in una riga: salva il file come TTF temporaneo, riaprilo, poi estrai il subset.
Cirillico e arabo: il prezzo pagato
Archivo non contiene cirillico. Nemmeno Instrument Sans. L'arabo manca in entrambi. Per queste due lingue serviva una famiglia diversa, e la scelta non è stata casuale.
- Russo: Roboto Flex. Era l’unico match strutturale: ha l’asse della larghezza. Nel CSS tutti i
font-variation-settingsi valori funzionano senza modifiche. Un solo file gestisce titoli e testo. La pagina russa resta più leggera di quella latina. - Arabo: Noto Sans Arabic. L'unico candidato con asse della larghezza. Un solo file da 144 KB copre tre ruoli, così la pagina araba scarica meno della pagina latina.
Il costo sta qui: in Noto Sans Arabic → e ✓ non contiene i glifi. Nella pagina araba, questi due segni arrivano dal font di riserva e appaiono leggermente diversi dai caratteri vicini. Invece di nasconderlo, lo abbiamo spiegato in un commento nel CSS. Altrimenti chi verrà dopo potrebbe scambiare la differenza per un errore.
Il layout da destra a sinistra ha richiesto un lavoro a parte: abbiamo invertito le frecce e sostituito le proprietà di posizione con gli equivalenti logici (margin-inline-start, inset-inline-start), così lo stesso CSS funziona bene in entrambe le direzioni.
Una piccola modifica: perché Martian Mono usa optional
Due famiglie su tre font-display:swap usa. Martian Mono optional. Il motivo lo abbiamo misurato: con swap, Martian arrivava tardi, faceva ricalcolare il pulsante del menu e causava uno spostamento di layout di 0,015. Siccome è precaricato, in pratica arriva in tempo. Nell’unico caso in cui non ce la fa, la pagina non si sposta e resta con il font di fallback.
La cartella dei font pesa 404 KB per dieci lingue. Nessuno la scarica tutta. Ogni pagina carica solo i file della propria lingua.