
⚡ Как загрузить веб-шрифты без потери скорости и ускорить отрисовку текста
Когда сайт грузится 3 секунды, а потом ещё секунду перерисовывает весь текст, посетитель уходит. Не к конкурентам, а просто закрывает вкладку. Проблема почти всегда в одном: веб-шрифты загружены без учёта производительности.
По данным HTTP Archive за 2025, около 84% сайтов используют кастомные веб-шрифты, и median-сайт делает 5 запросов к шрифтовым файлам общим весом под 400 КБ. При плохом соединении это 2-3 секунды блокировки рендеринга, когда пользователь видит пустой экран. А Google учитывает Cumulative Layout Shift от подмены шрифта в Core Web Vitals.
Четыре шага ниже, это не теория. Это практический минимум, который закрывает подавляющее большинство проблем с производительностью веб-шрифтов. Каждый шаг занимает от 5 до 15 минут.
💡 Быстрый обзор:
- Определитесь с форматами: woff2 как основной и woff как fallback, этого достаточно для всех современных браузеров.
- Добавьте preload для критичных шрифтов, чтобы браузер не ждал CSS, а начинал загрузку сразу.
- Проверьте font-face: local(), правильный порядок src, unicode-range для латиницы.
- Настройте font-display: swap, и посетитель видит текст мгновенно, даже пока шрифт ещё грузится.
Шаг 1: Используйте woff2 и woff, остальное не нужно
Форматов веб-шрифтов много: EOT, TTF, OTF, SVG. Но в 2026 году реально нужны только два.
woff2, современный стандарт. Файлы на 30% меньше woff при том же качестве, потому что используют brotli-сжатие вместо gzip. Поддержка браузерами, все evergreen-браузеры, включая мобильные Safari и Samsung Internet. Глобально, 98%+ пользователей.
woff, fallback для небольшой доли старых браузеров (Safari на iOS 11 и ниже, редкие корпоративные окружения). Тоже сжимается, работает везде с IE9+. Держите его последним в src, и браузер возьмёт woff2 если может, иначе откатится на woff.
EOT (Internet Explorer 8 и ниже) и TTF (сырой формат, без сжатия) в 2026 году не используйте. Доля таких браузеров, статистическая погрешность, а каждый лишний формат в src увеличивает CSS и путает браузер.
Если у вас файлы в TTF или OTF, конвертируйте через онлайн-генератор. Transfonter делает woff2 и woff одной операцией, показывая preview глифов и итоговый вес. Альтернатива, Font Squirrel Webfont Generator.
Шаг 2: Предзагрузите критичные шрифты через preload
Браузер узнаёт о шрифте из CSS, а CSS он читает после HTML. Пока доберётся, проходит 500-800 мс на среднем соединении. Preload режет эту задержку до нуля: браузер начинает качать шрифт как только встречает тег в <head>, не дожидаясь CSS.
Минимальный рабочий тег:
1 <link rel="preload" as="font" 2 href="/fonts/open-sans.woff2" 3 type="font/woff2" 4 crossorigin="anonymous">
Ключевое, crossorigin="anonymous". Без него браузер проигнорирует предзагруженный шрифт и скачает его повторно. Причина в том, что шрифты фетчатся анонимно (CORS), а preload без crossorigin делает обычный запрос, браузер считает это разными ресурсами и не сопоставляет.
Что предзагружать. Не каждый шрифт на сайте. Только тот, который используется для основного текста выше сгиба (above the fold): заголовок, body, навигация. Остальные подождут. Предзагрузка 4-5 файлов даёт diminishing returns и отбирает полосу у критичного контента.
Важный нюанс с Google Fonts и CDN. Если берёте шрифты с Google Fonts, файлы периодически обновляются, и preload-ссылка на старой версии приведёт к двойной загрузке (старая + новая). Вместо preload для CDN-шрифтов используйте <link rel="preconnect"> к домену шрифтов, это ускорит handshake без риска версионного расхождения:
1 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
Prefetch для второстепенных шрифтов. rel="prefetch" сообщает браузеру: «этот ресурс понадобится позже, загрузи когда основное готово». Подходит для шрифтов на внутренних страницах или для иконочных шрифтов в футере. Приоритет низкий, полосу не отбирает.
Современный гид по приоритизации ресурсов есть в документации web.dev.
Шаг 3: Оформите @font-face без ошибок
С виду @font-face простой. На практике в нём четыре тонких места, каждое влияет на скорость.
Пример правильного объявления:
1 @font-face { 2 font-family: 'Open Sans'; 3 font-weight: 400; 4 font-style: normal; 5 font-display: swap; 6 unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, 7 U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, 8 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, 9 U+FEFF, U+FFFD; 10 src: local('Open Sans'), 11 url('/fonts/open-sans.woff2') format('woff2'), 12 url('/fonts/open-sans.woff') format('woff'); 13 }
Разбор по пунктам:
local(): первым в src. Если у пользователя шрифт уже установлен в системе (Roboto на Android, Segoe UI на Windows, San Francisco на macOS), браузер возьмёт локальную копию и не будет качать ни байта. Всегда ставьте local() первой строкой в src. Имя берите из самого шрифтового файла: local('Open Sans') и local('Roboto Regular').
Порядок форматов. Браузер идёт по src слева направо и берёт первый формат, который понимает. Поэтому: local() → woff2 → woff. Никаких EOT/TTF/SVG в конце, только если у вас специфическая аудитория со старыми браузерами, и тогда они идут ПОСЛЕ woff (не до).
unicode-range, грузим только нужные глифы. Для латиницы достаточно диапазона U+0000-00FF (Basic Latin + Latin-1 Supplement). Это ~250 глифов против нескольких тысяч в полном наборе. Реальный вес файла падает в 3-5 раз. Не перегружайте диапазон, каждый лишний unicode-block добавляет глифы, которые никто не увидит. Для кириллических сайтов добавьте U+0400-04FF.
Порядок @font-face-блоков. Если у вас несколько начертаний (regular, bold, italic), обычное начертание (font-weight: 400) ставьте первым, браузер начнёт качать именно его.
Шаг 4: Включите font-display: swap, и попрощайтесь с FOIT
Flash of Invisible Text (FOIT), это когда браузер прячет текст на 3 секунды, ожидая шрифт. Пользователь видит пустую страницу. Flash of Unstyled Text (FOUT), текст сразу виден системным шрифтом, потом заменяется кастомным. Второе всегда лучше первого.
font-display: swap в @font-face делает именно это: текст рендерится мгновенно системным шрифтом, а когда кастомный загрузился, подменяется. Идеально для основного текста.
Другие значения и когда их применять:
swap, для body-текста. Текст виден сразу, замена плавная.optional, для декоративных шрифтов и иконок. Браузер решает, стоит ли качать шрифт вообще: при плохом соединении откажется и оставит системный. Период ожидания, 100 мс.block, короткая блокировка (обычно 3 секунды), потом текст виден, шрифт заменится когда загрузится. Почти не используется.fallback, компромисс: короткая блокировка, потом текст виден, шрифт заменится если успеет загрузиться быстро.
На практике для body-текста ставьте swap, для иконочных шрифтов и декора, optional. Этого хватает.
Поведение браузеров без font-display. Если не указать ничего, Chrome прячет текст до 3 секунд, Firefox, до 3 секунд, Safari, бесконечно, Edge, сразу показывает системный. С font-display: swap это поведение унифицируется, и результат предсказуем.
Как проверить результат
Проверьте свой сайт до и после на web.dev/measure, Lighthouse покажет «Ensure text remains visible during webfont load» отдельной строкой. Если аудит красный, ваш font-display не работает или отсутствует.
Для ручной проверки: откройте DevTools → Network, поставьте троттлинг «Slow 3G» и обновите страницу. Текст должен появиться системным шрифтом мгновенно, а не через 3 секунды пустого экрана.
На скриншотах ниже, разница между стандартным подходом и оптимизированным (тест на Slow 3G):

По умолчанию: текст скрыт, пока шрифт не загрузился

Оптимизированное поведение: текст виден сразу системным шрифтом
Видно невооружённым глазом: на первом скриншоте, белый экран, на втором, контент доступен мгновенно.
На конференции performance.now() 2024 Мэнди Майкл разбирает продвинутые стратегии, инкрементальный unicode-range, font slicing и работу с вариативными шрифтами. Для тех, кто хочет пойти дальше четырёх базовых шагов.
⁉️🤔 Частые вопросы
Зачем нужен woff, если woff2 поддерживается везде?
Оставшиеся пользователи старых iOS Safari (iOS 11 и ниже) и редких корпоративных окружений с locked-down браузерами не поддерживают woff2. Без woff-фолбэка эти пользователи увидят системный шрифт вместо вашего. Woff добавляет 15-20 КБ к набору, negligible цена за покрытие оставшейся доли.
Можно ли использовать Google Fonts и не париться?
Можно, и для большинства сайтов это оптимальный путь. Google Fonts автоматически отдаёт woff2 современным браузерам, использует CDN с геораспределением и поддерживает
display=swapпараметром в URL. Минусы: зависимость от внешнего CDN (privacy-соображения, GDPR), невозможность управлятьunicode-rangeи локальной установкой шрифтов. Если privacy и контроль важны, self-host шрифтов.
Как узнать, что шрифты реально тормозят сайт?
Lighthouse (вкладка Audits в Chrome DevTools) покажет аудит «Ensure text remains visible during webfont load». WebPageTest даст waterfall с таймингом каждого шрифтового запроса. Если шрифты стартуют позже первого CSS, preload не настроен. Если сдвиг макета больше 0.1, шрифт вызывает Cumulative Layout Shift, и Google это засчитывает в Core Web Vitals.
font-display: swap портит дизайн, текст «прыгает» при подмене?
Да, это известный минус swap. Боритесь двумя приёмами. Первый: задайте для текста
font-sizeиline-heightтакие же, как у системного fallback-шрифта, разница в метриках будет минимальной. Второй: используйте Font Style Matcher или модульsize-adjustв@font-face(доступен в современных браузерах), чтобы подогнать метрики кастомного шрифта под системный. После подгонки CLS будет нулевым.
Нужно ли предзагружать все шрифты на сайте?
Нет. Предзагружайте только critical шрифты, те, что формируют текст above the fold (первые 1-2 экрана). Остальные грузите штатно через CSS. Предзагрузка 5+ шрифтов забивает полосу и задерживает более важные ресурсы в очереди. На практике 1-2 preload-линка покрывают подавляющее большинство сценариев.
Стоит ли заморачиваться: четыре шага, четыре минуты
Настройка веб-шрифтов, не проект на неделю. Конвертация в woff2, правка @font-face, preload и font-display: swap, это 20-30 минут работы, даже если вы никогда этого не делали.
Выгода измеримая: текст становится видимым на 1.5-2.5 секунды раньше на Slow 3G. Core Web Vitals не штрафуют за сдвиг макета. И пользователь не уходит, глядя на белый экран.
Начните с одного шрифта, основного текстового. Сделайте четыре шага. Проверьте Lighthouse до и после. Разница в цифрах убедит лучше любых аргументов.



