Оптимизация шрифтов: font-display, preload, subset
Кастомные шрифты — распространённая причина медленного FCP и CLS. Браузер должен загрузить шрифт до отображения текста (или показать невидимый текст / системный шрифт). Правильная настройка устраняет оба симптома.
font-display — управление рендерингом
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap; /* показать fallback сразу */
}
| Значение | Поведение | Когда использовать |
|---|---|---|
auto |
Зависит от браузера | Не использовать |
block |
Скрыть текст до загрузки (FOIT) | Иконочные шрифты |
swap |
Fallback → основной при загрузке | Основной текст |
fallback |
100мс скрыт, потом swap | Баланс FCP/CLS |
optional |
Только если уже закеширован | Некритичные шрифты |
Для основного текста — swap. Для декоративных заголовков где FOUT (Flash of Unstyled Text) допустим — swap. Для иконочных шрифтов — block (иначе иконки отобразятся как символы).
Preload критичного шрифта
<head>
<!-- Preload до загрузки CSS -->
<link rel="preload"
href="/fonts/inter-regular.woff2"
as="font"
type="font/woff2"
crossorigin>
<!-- Если несколько начертаний — preload только используемые above-the-fold -->
<link rel="preload" href="/fonts/inter-700.woff2" as="font" type="font/woff2" crossorigin>
</head>
Preload только шрифты, используемые в первом экране. Preload всех начертаний замедляет загрузку.
Subset — только нужные символы
Полный Inter содержит латиницу, кириллицу, греческий, иврит — ~500 кБ. Подмножество только с нужными символами — 30–80 кБ.
/* unicode-range для кириллицы */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-cyrillic.woff2') format('woff2');
font-weight: 400;
font-display: swap;
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* Латиница — отдельный файл */
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-latin.woff2') format('woff2');
font-weight: 400;
font-display: swap;
unicode-range: U+0000-00FF, U+0131, U+0152-0153;
}
Браузер загружает только файлы с символами, встречающимися на странице.
Генерация subset через pyftsubset
# Установка
pip install fonttools brotli
# Создание subset с кириллицей + базовой латиницей
pyftsubset inter-regular.ttf \
--unicodes="U+0020-007E,U+00A0-00FF,U+0400-045F,U+0490-0491" \
--layout-features="kern,liga,calt" \
--flavor=woff2 \
--output-file=inter-regular-subset.woff2
Self-hosted vs Google Fonts
Google Fonts вводит DNS lookup + connection overhead для каждого нового пользователя. Self-hosted шрифты:
- Убирают cross-origin задержку
- Позволяют использовать HTTP/2 push или preload
- Работают без зависимости от стороннего CDN
# Скачать шрифт с правильными subset
# Используя google-webfonts-helper (gwfh.mranftl.com)
# или fontsource npm пакет
npm install @fontsource-variable/inter
/* Fontsource — автоматически включает нужные файлы */
@import '@fontsource-variable/inter/cyrillic.css';
@import '@fontsource-variable/inter/latin.css';
Компенсация CLS от font-swap
/* Подобрать метрики для fallback шрифта */
@font-face {
font-family: 'InterFallback';
src: local('Arial');
ascent-override: 90%;
descent-override: 22%;
line-gap-override: 0%;
size-adjust: 107%;
}
body {
font-family: 'Inter', 'InterFallback', sans-serif;
}
Инструменты для подбора значений: fontaine npm-пакет или next/font (для Next.js — автоматически).
Variable fonts
Один файл вместо отдельных файлов для каждого weight:
@font-face {
font-family: 'Inter';
src: url('/fonts/inter-variable.woff2') format('woff2-variations');
font-weight: 100 900; /* диапазон */
font-display: swap;
}
/* Использование */
h1 { font-weight: 700; }
body { font-weight: 400; }
.light { font-weight: 300; }
Variable font Inter (~170 кБ subset кириллица+латиница) vs. отдельные файлы для 400 + 700 (~120 кБ). Выгодно при ≥ 3 начертаниях.
Срок оптимизации: 4–8 часов: скачать шрифты, сделать subset, настроить preload и CSS.







