Веб-шрифты и производительность
Что это такое
Веб-шрифт — это файл гарнитуры, который браузер скачивает, прежде чем сможет отрисовать текст этой гарнитурой. Загрузка такого файла — задача планирования: на мгновение у страницы есть текст, который она ещё не может нарисовать. Ждать, подставить запасной шрифт или подменить его позже — три способа повести себя в этот момент, и каждый даёт свой опыт пользователя.
Почему это важно
Текст, который исчезает и появляется снова, выглядит сломанным. А текст, который смещается после того, как макет устоялся, — одна из самых частых причин плохой оценки сдвига макета. Файлы шрифтов к тому же часто среди самых крупных ресурсов на странице: целое семейство может перевесить JavaScript. Поэтому правильная загрузка — та разница, из-за которой страница либо сразу показывает читаемый текст, либо мигает невидимым, либо роняет содержимое вниз через треть секунды после того, как всё выглядело готовым.
Ключевые идеи
Загружайте один формат, подмножество и со своего источника
Современный файл woff2 сжат и поддерживается везде, где это важно. Подмножество, то есть включение только тех символов, которые сайт действительно использует, часто уменьшает файл более чем вдвое. Отдача со своего источника избавляет от соединения со сторонним доменом и лишнего поиска DNS.
@font-face {
font-family: "Body";
src: url("/fonts/body.woff2") format("woff2");
font-weight: 400 700;
font-display: swap;
unicode-range: U+0000-00FF;
}
Вариативный шрифт упаковывает несколько начертаний в один файл: семейство из четырёх начертаний может стоить почти как одно.
Выбирайте стратегию font-display осознанно
swap сразу отрисовывает запасной шрифт и заменяет его, когда основной придёт: текст остаётся читаемым, а замена гарантированно видна. optional даёт шрифту очень короткое окно. Если основной не успел, запасной остаётся на всю загрузку страницы, и подмены не происходит вовсе. block скрывает текст на мгновение и должен использоваться редко, если вообще.
Согласуйте запасной шрифт с основным
Сдвиг возникает потому, что метрики запасного шрифта отличаются от метрик загруженного. Свести его почти к нулю помогает цепочка запасных шрифтов, подобранная по близким пропорциям, вместе с переопределением метрик или size-adjust на локальном запасном начертании.
@font-face {
font-family: "Body Fallback";
src: local("Arial");
size-adjust: 105%;
ascent-override: 92%;
}
body { font-family: "Body", "Body Fallback", sans-serif; }
Предзагружайте скупо и только то, что нужно первому экрану
rel="preload" запускает скачивание раньше: это помогает шрифту, который нужен первому экрану, и зря тратит трафик на шрифт, который встречается только в подвале. Атрибут crossorigin обязателен даже для шрифта со своего источника: без него файл скачивается дважды.
Подумайте, не загружать шрифт вообще
Хорошо выбранная системная цепочка отрисовывается мгновенно, ничего не стоит и совпадает с операционной системой, которую читатель уже выбрал. Там, где текст и есть продукт, системная цепочка часто оказывается лучшим инженерным ответом. А узнаваемая гарнитура оправдывает свои байты, когда на ней держится бренд.
Практика
Измерьте сдвиг с переопределением запасного шрифта и без него
Загрузите один пользовательский шрифт на страницу и зафиксируйте сдвиг макета в трассировке производительности. Затем добавьте запасное начертание с исправленными метриками и зафиксируйте снова.
Готово, когда: вторая трассировка показывает меньший сдвиг, чем первая, а текст читаем в обеих.
Сделайте подмножество одного шрифта и сравните размеры
Возьмите шрифт, который использует ваш проект, и сведите его к символам, которые сайт действительно содержит. Сравните размеры файлов и измерьте загрузку снова.
Готово, когда: файл подмножества меньше исходного, страница отрисовывается так же, и вы можете назвать, что сломается, если содержимое сменит язык.
Частые ошибки
font-display: blockпо умолчанию — текст невидим всё время загрузки шрифта, а на медленном соединении это секунды; исправить: используйтеswapилиoptional.- Загрузка целого семейства ради двух начертаний — страница платит за глифы, которые никогда не показывает; исправить: делайте подмножество и предпочитайте вариативный шрифт.
- Отсутствие
crossoriginу предзагруженного шрифта — шрифт скачивается дважды; исправить: всегда задавайте его для предзагрузки шрифтов. - Предзагрузка всех шрифтов — трафик тратится на начертания ниже первого экрана, а что-то более важное задерживается; исправить: предзагружайте только то, что отрисовывает первый экран.
- Тестирование на быстром локальном соединении — локально подмена не происходит, и проблема уходит в продакшен; исправить: ограничивайте сеть до медленного профиля при проверке.
Что читать дальше
- Типографическая шкала и ритм (02-frontend/18-web-typography/01-type-scales-and-rhythm) — размеры и запасные шрифты, под которые подгоняются эти гарнитуры.
- Веб-производительность (Core Web Vitals) (02-frontend/26-web-performance-core-web-vitals) — где загрузка шрифтов проявляется как сдвиг макета и заблокированная отрисовка.
- Каскадные таблицы стилей (CSS) (02-frontend/05-css) —
@font-face, каскад и пользовательские свойства, хранящие цепочку шрифтов.