Logboek · Notitie 002 · Typografie

Tien talen, drie fontbestanden

Bij een site in tien talen sneuvelt meestal als eerste het fontbudget. Dit keer niet. Voor Cyrillische en Arabische tekens betaalden we wel een andere prijs. Die verstoppen we niet.

Serhat Belen

Oprichter, BLN Global · · 6 min lezen

Kort antwoord

Met dezelfde drie lettertypen uit Google Fonts zou een Turkse pagina 6 bestanden van twee externe domeinen downloaden, samen 250 KB. Vanaf onze eigen server zijn dat 3 bestanden van één domein en 165 KB. De meeste winst komt doordat we ongebruikte assen vastzetten, niet door subsets. Voor Cyrillische en Arabische tekens moesten we een apart lettertype kiezen. In het Arabisch komen sommige symbolen daardoor uit een reservelettertype.

De typografie van de site draaide op drie families: Archivo voor koppen, Instrument Sans voor lopende tekst, Martian Mono voor cijfers en labels. Alle drie zijn variable fonts. In vijf talen ging dat goed. Bij de stap naar tien talen groeiden twee problemen tegelijk: te veel bytes en te weinig alfabetdekking.

Wat we met wat vergelijken

Ruwe TTF-bestanden vergelijken met onze WOFF2-bestanden geeft een vertekend beeld. Het grootste verschil komt door compressie, niet door de subset. De echte vergelijking is met het bestaande alternatief: hoeveel zou je downloaden als dezelfde drie families van Google Fonts kwamen?

Niet alle negen bestanden komen binnen. De browser unicode-range bekijkt het veld en haalt alleen de subsets op die de pagina nodig heeft. Voor een Turkse pagina is dat per familie latin + latin-ext:

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 Wat de Turkse pagina downloadt: 250 KB (6 bestanden)
We haalden de CSS van Google Fonts op, lazen per @font-face-blok de unicode-range en maten de bestanden één voor één. De items met een pijl worden op een Turkse pagina echt gedownload.
250 KB / 6 bestanden / 2 externe origins165 KB / 3 bestanden / één origin

Fontlast van de Turkse pagina

Hoe we maten Links staat de meting hierboven. Rechts die uit deze repository archivo.woff2 + instrument.woff2 + martian.woff2 de echte bestandsgrootte op schijf.

We wonnen meer dan bytes: zes requests werden er drie, en de DNS + TLS-handshake met twee externe origins verdween. Zo verdween de resource die de first paint blokkeerde in de notitie over de laatste 18 punten Je leest het.

Drie valkuilen

Eén: de subset latin-ext mist de gewone Latijnse letters

Bij de eerste poging downloadden we het latin-ext-bestand van Google Fonts en maakten we er een subset van. Het resultaat telde 130 gliefen, maar geen cijfers. De reden is simpel: latin-ext is boven op latin een extra is een subset, geen volledig alfabet. Download het volledige variabele lettertype uit de google/fonts-repository en maak zelf de subset.

Twee: zet je ongebruikte assen niet vast, dan wordt het bestand vijf keer zo groot

Elke as van een variabel lettertype maakt het bestand zwaarder. Het ontwerp gebruikt alleen gewicht en breedte. Zet je de andere assen niet vast op hun standaardwaarde, dan blijft alle data in het bestand.

volledig = {a.axisTag: a.defaultValue for a in t['fvar'].axes if a.axisTag not in assen} volledig.update(assen) # Assen naast wght/wdth krijgen hun standaardwaarde, # anders wordt het bestand vijf keer zo groot
De as vastzetten vóór het subsetten bespaart meer ruimte dan het subsetten zelf.

Drie: gvar laadt lui

Toen we na het vastzetten van de as met fontTools meteen wilden subsetten KeyError: space wordt opgehaald. De oorzaak is lazy loading van variable glyph-data (gvar): na het vastzetten lijkt het object in het geheugen consistent, maar de subsetter kan het niet lezen. De omweg is suf, maar past op één regel: sla het bestand tijdelijk op als TTF, open het opnieuw en maak dan de subset.

Cyrillisch en Arabisch: de prijs

Archivo heeft geen Cyrillisch, Instrument Sans ook niet. Arabisch zit in geen van beide. Voor die twee talen moesten we een andere familie kiezen. Die keuze was niet willekeurig.

  • Russisch: Roboto Flex. De enige structurele match was de breedte-as. Dus alles in de CSS font-variation-settings werkt zonder de waarden te wijzigen. Eén bestand bedient koppen en broodtekst. De Russische pagina blijft lichter dan de Latijnse.
  • Arabisch: Noto Sans Arabic. De enige kandidaat met een breedte-as. Eén bestand van 144 KB vervult alle drie de rollen. Daardoor downloadt de Arabische pagina minder dan de Latijnse.

De prijs zit hier: in Noto Sans Arabic en bevat die tekens niet. Op de Arabische pagina komen ze uit het reservelettertype en wijken ze iets af van de letters ernaast. We hebben dat als commentaar in CSS gezet. Anders ziet de volgende persoon hetzelfde verschil en denkt die dat het een fout is.

Een rechts-naar-linksindeling vraagt apart werk: we draaiden de pijlen om en vervingen positie-eigenschappen door hun logische tegenhangers (margin-inline-start, inset-inline-start), zodat dezelfde CSS in beide richtingen goed werkt.

Een kleine keuze: waarom Martian Mono op optional staat

Twee van de drie families font-display:swap gebruikt. Martian Mono optional. De reden is gemeten: met swap komt Martian laat binnen, waardoor de menuknop opnieuw wordt gemeten en een layout shift van 0,015 ontstaat. Omdat hij vooraf wordt geladen, is hij in de praktijk toch op tijd. In dat ene geval waarin dat niet lukt, schuift de pagina niet. Hij blijft op het fallbackfont staan.

De lettertypemap voor tien talen is 404 KB. Niemand downloadt alles. Elke pagina haalt alleen de bestanden voor haar eigen taal op.

Veelgestelde vragen

Kan ik Google Fonts beter zelf hosten?

In bytes niet altijd, in verbindingen meestal wel. Google Fonts maakt contact met twee aparte origins. Elke nieuwe origin betekent DNS-resolutie en een TLS-handshake. Bij ons was het verschil gemeten: 250 KB / 6 bestanden / 2 origins werd 165 KB / 3 bestanden / één origin.

Wat levert meer op: subsetten of de as vastzetten?

De as vastzetten. Elke as van een variabel lettertype die je niet gebruikt, neemt ruimte in. Zet je hem niet vast, dan wordt het bestand een paar keer groter. Daarna pas maak je de subset.

Is de subset latin-ext genoeg voor het Turks?

Nee, latin-ext is op zichzelf voor geen enkele taal genoeg. Het is een aanvulling op latin en bevat geen basisletters of cijfers. Download het volledige variabele lettertype en maak zelf de subset.

font-display: swap of optional?

Vormt de tekst de kern van de pagina en is het lettertype vooraf geladen, dan is optional veiliger: komt het te laat, dan verschuift de pagina niet en blijft de fallback staan. Bij ons zorgde swap op Arabische pagina's voor 0,287 CLS. optional bracht dat terug naar nul.

Welk lettertype koos je voor Arabisch en Russisch, en waarom?

Voor Russisch Roboto Flex, voor Arabisch Noto Sans Arabic. Het ging niet om smaak. Het ging om de bouw: allebei hebben ze een breedte-as, dus de bestaande font-variation-settings waarden draaien zonder aanpassing.

Bronnen

Gerelateerd werk