Блокнот · Заметка 002 · Типографика

Десять языков, три файла шрифтов

При запуске сайта на десяти языках первым трещит бюджет на шрифты. Мы уложились. Но за кириллицу и арабские символы пришлось заплатить иначе. Эту цену мы не скрыли.

Serhat Belen

Основатель BLN Global · · Читать 6 мин

Короткий ответ

Если бы те же три шрифта загружались из Google Fonts, турецкая страница скачивала бы 6 файлов на 250 KB с двух внешних источников. С нашего сервера приходят 3 файла на 165 KB из одного источника. Основную экономию дали не подмножества символов, а фиксация неиспользуемых осей. Для кириллицы и арабского пришлось выбрать отдельные семейства. Поэтому часть символов в арабской версии берётся из запасного шрифта.

Типографика сайта держалась на трёх гарнитурах: Archivo для заголовков, Instrument Sans для текста, Martian Mono для чисел и меток. Все три шрифта переменные. На пяти языках всё было спокойно. Когда дошли до десяти, сразу выросли две проблемы: вес загрузки и покрытие алфавитов.

Что с чем сравниваем

Сравнивать исходные TTF с опубликованными WOFF2 нечестно. Большую часть разницы даёт сжатие, а не сокращённый набор символов. Сравнивать надо с реальной альтернативой: сколько пришлось бы скачать, если бы те же три семейства загружались из Google Fonts.

Все девять файлов не качаются. Браузер unicode-range смотрит на поле и загружает только нужные странице подмножества. Для турецкой страницы это 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 Турецкая страница скачает: 250 KB (6 файлов)
Мы скачали CSS Google Fonts, у каждого блока @font-face прочитали unicode-range и измерили файлы по одному. Стрелками отмечены те, которые реально загружаются на турецкой странице.
250 KB / 6 файлов / 2 внешних источника165 KB / 3 файла / один источник

Вес шрифтов на турецкой странице

Как мерили Слева замер выше. Справа результат из этого репозитория archivo.woff2 + instrument.woff2 + martian.woff2 реальный вес файлов на диске.

Помимо байтов, выиграли еще в двух местах: шесть запросов стали тремя, а DNS + TLS-рукопожатия к двум внешним источникам исчезли. Как мы закрыли ресурс, который блокировал первую отрисовку в заметке про последние 18 баллов рассказываем.

Три ловушки

Первое: в подмножестве latin-ext нет базовых латинских букв

Сначала мы скачали файл latin-ext из Google Fonts и собрали подмножество. Получили 130 глифов без цифр. Причина проста: latin-ext дополняет latin, а не заменяет его. Это отдельный доп. это подмножество, а не полный алфавит. Скачай полный вариативный шрифт из репозитория google/fonts и сам выдели нужное подмножество.

Второе: если не зафиксировать неиспользуемые оси, файл вырастет в пять раз

Каждая ось вариативного шрифта утяжеляет файл. В макете нужны только вес и ширина. Если не зафиксировать остальные оси на значениях по умолчанию, их данные останутся в файле.

tam = {a.axisTag: a.defaultValue for a in t['fvar'].axes if a.axisTag not in eksen} tam.update(eksen) # Оси, кроме wght/wdth, фиксируются на значениях по умолчанию, # иначе файл вырастает в пять раз
Зафиксируй ось до сабсета, и сэкономишь больше места, чем на одном сабсете.

Третья: gvar грузится лениво

после фиксации оси через fontTools попытка сразу собрать сабсет KeyError: space получается. Причина в ленивой загрузке данных переменных глифов (gvar): после фиксации объект в памяти выглядит цельным, но сабсеттер не может его прочитать. Обход кривой, зато в одну строку: сохрани файл как временный TTF, открой заново и потом вырежи подмножество.

Кириллица и арабский: за что платим

В Archivo нет кириллицы, в Instrument Sans тоже. Арабского письма нет ни в одном. Для этих двух языков пришлось выбрать отдельные семейства, и выбор был не на вкус.

  • Русский: Roboto Flex. По структуре совпало только одно: есть ось ширины. Значит, все font-variation-settings значения работают без изменений. Один файл обслуживает заголовки и основной текст. Русская страница остаётся легче страницы на латинице.
  • Арабский: Noto Sans Arabic. Единственный кандидат с осью ширины. Один файл весит 144 КБ и закрывает сразу три роли, поэтому арабская страница загружает меньше страницы на латинице.

Цена вот где: Noto Sans Arabic и Этих глифов нет. На арабской странице два знака берутся из резервного шрифта и немного отличаются от соседних. Мы не стали маскировать разницу и оставили комментарий в CSS. Иначе следующий разработчик примет её за ошибку.

Вёрстку справа налево мы настроили отдельно: развернули стрелки и заменили свойства позиционирования логическими аналогами (margin-inline-start, inset-inline-start), поэтому один CSS верно работает в обоих направлениях.

Небольшая настройка: почему Martian Mono подключён опционально

Две из трёх гарнитур font-display:swap использует Martian Mono. optional. Причину мы измерили: со swap Martian приходит поздно, заставляет меню заново измерить кнопку и даёт сдвиг вёрстки 0,015. Из-за предзагрузки он почти всегда успевает. Если не успел, страница не прыгает и остаётся на запасном шрифте.

Папка со шрифтами для десяти языков весит 404 КБ. Целиком её не скачивает никто. Каждая страница загружает файлы только для своего языка.

Частые вопросы

Стоит ли хранить шрифты у себя вместо Google Fonts?

По байтам не всегда, по соединениям чаще да. Google Fonts ходит к двум разным источникам, а каждый новый источник добавляет DNS и TLS. У нас замер показал: вместо 250 KB / 6 файлов / 2 источника получили 165 KB / 3 файла / один источник.

Что дает больше экономии: сабсет или фиксация оси?

Зафиксируй ось. Каждая неиспользуемая ось вариативного шрифта занимает место в файле. Не зафиксируешь её, файл раздуется в несколько раз. Подмножество режь после.

Подмножества latin-ext достаточно для турецкого?

Нет, самого по себе его недостаточно ни для одного языка. latin-ext дополняет latin и частично с ним пересекается. Базовых букв и цифр в нём нет. Скачай полный вариативный шрифт и сам собери нужное подмножество.

Для font-display брать swap или optional?

Если текст собирает основное тело страницы и шрифт предзагружен, optional безопаснее: если шрифт опоздал, страница не прыгает и остается на запасном. У нас swap давал сдвиг 0,287 на арабских страницах. optional свел его к нулю.

Какие шрифты вы выбрали для арабского и русского и почему?

Для русского взяли Roboto Flex, для арабского Noto Sans Arabic. Выбор не про эстетику: у обоих есть ось ширины, значит текущий CSS font-variation-settings работает с теми же значениями.

Источники

Похожие работы