Notes · Notatka 002 · Typografia
Dziesięć języków, trzy pliki fontów
Gdy uruchamiasz stronę w dziesięciu językach, najpierw wykłada się budżet na fonty. Tutaj wytrzymał. Cyrylica i alfabet arabski miały jednak swoją cenę. Pokazaliśmy ją bez ukrywania kosztów.
Założyciel, BLN Global · · 6 min czytania
Krótka odpowiedź
Gdybyśmy pobierali te same trzy fonty z Google Fonts, strona po turecku ściągałaby 6 plików o rozmiarze 250 KB z dwóch zewnętrznych źródeł. Z naszego serwera pobiera 3 pliki, 165 KB, z jednego źródła. Większość oszczędności daje zablokowanie nieużywanych osi, a nie podział na podzbiory. Dla cyrylicy i alfabetu arabskiego musieliśmy wybrać osobne rodziny. W arabskim część symboli pochodzi przez to z fontu zastępczego.
Typografia strony opierała się na trzech rodzinach: Archivo do nagłówków, Instrument Sans do tekstu, Martian Mono do liczb i etykiet. Wszystkie trzy były fontami zmiennymi. Przy pięciu językach mieliśmy spokój. Przy dziesięciu naraz urosły dwa problemy: pobierane bajty i zakres alfabetów.
Co z czym porównujemy
Porównywanie surowych plików TTF z opublikowanymi plikami WOFF2 byłoby nieuczciwe. Większość różnicy wynika z kompresji, nie z podziału na podzbiory. Trzeba porównać je z realną alternatywą: ile danych pobrałaby przeglądarka, gdyby te same trzy rodziny pochodziły z Google Fonts.
Nie pobierze wszystkich dziewięciu plików. Przeglądarka unicode-range sprawdza pole i pobiera tylko podzbiory potrzebne stronie. Dla strony po turecku oznacza to latin + latin-ext na każdą rodzinę:
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 Turecka strona pobierze: 250 KB (6 plików)
Ciężar fontów na tureckiej stronie
archivo.woff2 + instrument.woff2 + martian.woff2 rzeczywisty rozmiar plików na dysku.Poza bajtami zyskaliśmy jeszcze dwie rzeczy: sześć żądań spadło do trzech, a DNS + TLS do dwóch zewnętrznych źródeł zniknęły całkiem. Jak zamknęliśmy problem zasobu blokującego pierwsze malowanie w notatce o ostatnich 18 punktach opisujemy.
Trzy pułapki
Po pierwsze: podzbiór latin-ext nie zawiera podstawowych liter łacińskich
Przy pierwszej próbie pobraliśmy plik latin-ext z Google Fonts i utworzyliśmy z niego podzbiór. Wynik miał 130 glifów, ale nie zawierał cyfr. Powód był prosty. latin-ext to nakładka na latin. dodatek to podzbiór, a nie pełny alfabet. Pobierz cały font zmienny z repozytorium google/fonts i sam wytnij potrzebny podzbiór.
Po drugie: bez zablokowania nieużywanych osi plik rośnie pięciokrotnie
Każda oś fontu zmiennego zwiększa plik. Projekt używa tylko grubości i szerokości. Jeśli nie zablokujesz pozostałych osi na wartościach domyślnych, ich dane zostają w pliku.
pelny = {a.axisTag: a.defaultValue for a in t['fvar'].axes if a.axisTag not in osie} pelny.update(osie) # osie inne niż wght i wdth blokujemy na wartościach domyślnych, # inaczej plik rośnie pięciokrotnie
Po trzecie: gvar ładuje się leniwie
gdy po zablokowaniu osi w fontTools od razu próbujesz wyciąć podzbiór KeyError: space robimy subset. Powód: leniwe ładowanie danych glifów zmiennych (gvar). Po przypięciu obiekt wygląda w pamięci spójnie, ale narzędzie do subsetowania go nie odczyta. Obejście jest kręte, lecz mieści się w jednej linijce: zapisz plik jako tymczasowy TTF, otwórz go ponownie, potem zrób subset.
Cyrylica i arabski: cena, którą płacisz
Archivo nie ma cyrylicy. Instrument Sans też nie. Żaden z nich nie ma arabskiego. Dla tych dwóch języków musieliśmy wybrać osobne rodziny, a wybór nie był przypadkowy.
- Rosyjski: Roboto Flex. Jedyne dopasowanie w strukturze: oś szerokości. Czyli wszystkie ustawienia w CSS
font-variation-settingsdziała bez zmiany wartości. Jeden plik obsługuje nagłówki i tekst główny. Strona rosyjska pozostaje lżejsza od łacińskiej. - Arabski: Noto Sans Arabic. Jedyny kandydat z osią szerokości. Jeden plik ma 144 KB i pełni trzy role, więc strona arabska pobiera mniej danych niż łacińska.
Cena jest tutaj: w Noto Sans Arabic → i ✓ nie ma tych znaków. Na arabskiej stronie oba pochodzą z fontu zastępczego i wyglądają trochę inaczej niż sąsiednie znaki. Zamiast to ukrywać, opisaliśmy powód w komentarzu CSS. Kolejna osoba zobaczy tę różnicę i uzna ją za błąd.
Układ od prawej do lewej wymaga osobnej pracy: odwróciliśmy kierunek strzałek i zastąpiliśmy właściwości pozycjonowania ich logicznymi odpowiednikami (margin-inline-start, inset-inline-start), dzięki czemu ten sam CSS działa poprawnie w obu kierunkach.
Mała zmiana: dlaczego Martian Mono ma optional
Dwie z trzech rodzin font-display:swap używa. Martian Mono optional. Powód mamy z pomiaru: przy swap Martian przychodzi późno, każe ponownie zmierzyć przycisk menu i robi przesunięcie układu 0,015. Po preloadzie w praktyce zdąża. Gdy raz nie zdąży, strona nie skacze, tylko zostaje przy foncie zastępczym.
Folder z fontami dla dziesięciu języków zajmuje łącznie 404 KB. Nikt nie pobiera całości. Każda strona ładuje tylko pliki swojego języka.