Веб-шрифты: как подключать быстро и без скачков вёрстки
Практика3 минРедакция Innovialabs
Коротко
Отдавайте шрифты в WOFF2 со своего домена, разбивайте их на подмножества по unicode-range, предзагружайте только главный файл, задайте font-display и подгоните метрики запасного шрифта — тогда текст появится сразу, а вёрстка не прыгнет.
Короткий ответ
Шрифты тормозят сайт двумя способами: текст долго не появляется, а когда шрифт загрузился — строки меняют ширину и высоту, и страница прыгает (это ухудшает метрику CLS). Рецепт:
- Формат WOFF2.
- Сабсеттинг: только нужные символы, кириллица и латиница отдельными файлами.
- Self-hosting на своём домене.
- preload для одного-двух ключевых файлов.
- font-display, подходящий задаче.
- Подгонка метрик запасного шрифта, чтобы замена была незаметной.
WOFF2 и меньше начертаний
WOFF2 сжимает шрифты лучше старых форматов и поддерживается всеми актуальными браузерами. TTF и EOT в 2020-х подключать не нужно.
Главная экономия — в количестве файлов. Каждое начертание (400, 500, 700, курсив) — отдельная загрузка. Если шрифт есть в формате variable font, один файл заменит несколько начертаний. Проверьте дизайн: часто хватает двух-трёх весов.
Сабсеттинг: кириллица и латиница
Полный шрифт содержит греческий, вьетнамский, символы и прочее, что вашему сайту не нужно. Разделите его на подмножества и укажите unicode-range — браузер скачает файл, только если на странице есть такие символы.
@font-face {
font-family: "Inter";
src: url("/fonts/inter-latin.woff2") format("woff2");
font-weight: 100 900;
font-display: swap;
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F;
}
@font-face {
font-family: "Inter";
src: url("/fonts/inter-cyrillic.woff2") format("woff2");
font-weight: 100 900;
font-display: swap;
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
Для узбекской латиницы проверьте символы ‘ и ’ (U+2018, U+2019) — они должны попадать в один из диапазонов. Нарезать файлы можно утилитой pyftsubset из пакета fonttools.
Self-hosting или Google Fonts
| Свой домен | Google Fonts | |
|---|---|---|
| Соединения | Без лишних | Отдельные домены для CSS и файлов |
| Кэш между сайтами | Нет | Тоже нет: браузеры разделяют кэш по сайтам |
| Контроль | Полный: сабсеты, preload, заголовки | Ограничен |
| Приватность | Запросы не уходят третьей стороне | Запросы идут на внешний сервис |
Раньше аргументом за Google Fonts был общий кэш, но современные браузеры изолируют кэш по сайтам, и это преимущество ушло. Поэтому чаще выгоднее хостить шрифты у себя. Фреймворки умеют делать это автоматически: например, next/font скачивает шрифты при сборке и отдаёт их с вашего домена.
preload: точечно
<link rel="preload" href="/fonts/inter-cyrillic.woff2"
as="font" type="font/woff2" crossorigin>
- Атрибут crossorigin обязателен даже для своего домена, иначе файл скачается дважды.
- Предзагружайте один-два файла: основной текст и, возможно, заголовки. Preload всего подряд конкурирует с CSS и картинками.
font-display: что выбрать
- swap — текст сразу показывается запасным шрифтом, потом заменяется. Хорош для основного текста, но без подгонки метрик даёт скачок.
- optional — если шрифт не успел за очень короткое время, браузер остаётся на запасном. Скачков нет, но фирменный шрифт может не показаться при первом визите.
- fallback — компромисс между ними.
- block — прячет текст до загрузки. Для основного текста почти никогда не нужен.
Подгонка метрик запасного шрифта
Скачок происходит потому, что у Arial и вашего шрифта разная ширина букв и высота строк. Создайте «подогнанный» запасной шрифт:
@font-face {
font-family: "Inter Fallback";
src: local("Arial");
size-adjust: 107%;
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
}
body {
font-family: "Inter", "Inter Fallback", sans-serif;
}
Значения выше — пример: для каждого шрифта их нужно рассчитать по его метрикам. Это делают инструменты вроде Fontaine или Capsize, а next/font генерирует такой фолбэк сам.
Частые ошибки
- Подключать шрифт через
@importвнутри CSS — это лишний последовательный запрос. - Грузить шесть начертаний, из которых используется два.
- Забыть
crossoriginв preload. - Отдавать шрифты без долгого кэширования: файлы со хэшем в имени можно кэшировать надолго.