Шрифты тормозят сайт: как ускорить или убрать Google Fonts
Self-hosted шрифты, font-display swap, subsetting и отказ от Google Fonts CDN. Как ускорить веб-шрифты на 1.5-2 секунды.
Содержание
- Что вообще тормозит, когда мы говорим про шрифты
- Главные ошибки, которые делают сайты со шрифтами
- Как сделать self-hosted шрифты правильно
- Variable Fonts: один файл вместо десяти
- Особые случаи на популярных движках
- Замер до и после: что должно поменяться
- Чек-лист настройки шрифтов
- Когда стоит делегировать
- Частые вопросы
Шрифт на 60 КБ грузится за десятую долю секунды, но при кривом подключении даёт до полутора секунд задержки текста: браузер ждёт файл и не рисует заголовки. Лечится тремя вещами: свой хостинг шрифтов, формат woff2 и правило показывать запасной шрифт сразу.
Веб-шрифт это маленький файл, который влияет на скорость сильнее, чем кажется. Один WOFF2 на 60 КБ грузится за 100 миллисекунд, и если он подключён криво, эти 100 мс превращаются в 1.5 секунды видимой задержки текста. Браузер ждёт, пока шрифт прилетит, и не показывает заголовки. Пользователь смотрит на пустые места, ничего не понимает, нервничает.
В России к этому добавляется отдельный слой проблем: Google Fonts CDN периодически ходит со скоростью улитки или вовсе не отвечает, и сайты, которые в 2018-м поставили <link> на fonts.googleapis.com, в 2026-м висят на каждом первом обновлении страницы. Разберу, как починить шрифты раз и навсегда.

Что вообще тормозит, когда мы говорим про шрифты
Цепочка событий при загрузке страницы со сторонним шрифтом:
- Браузер парсит HTML, видит ссылку на
fonts.googleapis.com/css2?family=.... - Делает DNS-запрос к
fonts.googleapis.com. - Открывает TCP и TLS-соединение. RTT в 2026 для российских пользователей до Google это 50-200 мс.
- Скачивает CSS с описанием шрифта.
- Парсит CSS, видит ссылку на
fonts.gstatic.com/...woff2. - DNS, TCP, TLS для нового домена.
- Скачивает сам шрифт.
- Применяет шрифт к тексту.
Это два DNS, два TLS, две физические передачи. Если пользователь в Перми, а серверы Google в Хельсинки или Дублине, суммарная задержка легко уезжает за 800-1500 миллисекунд. Всё это время текст либо невидимый (FOIT), либо нарисован системным шрифтом и потом перерисовывается (FOUT).
Self-hosted шрифт даёт всё то же самое только в одном домене, на одном TLS, и часто из CDN рядом с пользователем. Разница на средней мобильной сети 500-800 миллисекунд, на медленной до 2 секунд.
Главные ошибки, которые делают сайты со шрифтами
Ошибка 1: подключение Google Fonts CDN
С 2022 года RU-аудитория стабильно жалуется на медленный или недоступный Google Fonts. Я регулярно вижу WordPress-темы и Tilda-шаблоны, у которых в <head> лежит:
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
Кроме скорости, у этого подключения ещё есть юридические сложности: по 152-ФЗ передача IP-адреса пользователя на серверы за рубежом без отдельного согласия трактуется как трансграничная передача персональных данных. На большинстве сайтов это никого не волнует, пока не приходит проверка РКН по жалобе. Поэтому отказ от Google Fonts CDN это и про скорость, и про закон.
Как исправить: скачать шрифт, положить локально, подключить через @font-face. Подробности ниже.
Ошибка 2: подключение десяти стилей одного шрифта
Часто в <link> тянется такое:
<link href="...family=Inter:wght@100;200;300;400;500;600;700;800;900&family=Roboto:..." rel="stylesheet">
В реальности на странице используется два-три начертания. Остальные семь скачиваются и лежат в кеше зря. Каждое лишнее начертание это 30-80 КБ.
Как исправить: посмотреть в дизайне сайта, какие стили реально нужны. Обычно достаточно regular и bold. Можно добавить medium или italic. Десять начертаний на одном сайте это излишество.
Ошибка 3: подключение шрифта со всеми кириллическими и латинскими символами
Шрифт с поддержкой кириллицы, латиницы, греческого, вьетнамского, азиатских языков весит в разы больше, чем нужно. Subsetting (выборка только нужных диапазонов) экономит 40-70 процентов веса.
Для русскоязычного сайта обычно достаточно: латинский базовый, латинский расширенный, кириллица, кириллица расширенная. Без вьетнамского и греческого.
Ошибка 4: font-display не указан
Без font-display браузер по умолчанию ведёт себя как block: до 3 секунд текст вообще не показывается, ждёт шрифт. На медленной сети это катастрофа: первый просмотр сайта это белый экран.
Лечение: font-display: swap для большинства случаев или font-display: optional для некритичных шрифтов.
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
swap показывает текст системным шрифтом сразу и перерисовывает, когда придёт кастомный.
optional ждёт 100 мс. Если шрифт за это время не пришёл, текст рисуется системным и в этой сессии больше не подменяется. Самый щадящий вариант для CLS.
Ошибка 5: подключение шрифта через @import в CSS
@import url('https://fonts.googleapis.com/css2?family=Inter');
Это добавляет ещё один уровень последовательной загрузки: сначала качается ваш CSS, потом он просит у Google ещё один CSS, потом тот просит шрифт. Каждое звено это RTT. Жесть.
Лечение: подключать через <link> в <head>, а лучше вообще локально.
Как сделать self-hosted шрифты правильно
Минимальный pipeline на любой современной CMS.
Шаг 1: скачайте нужные начертания
Идёте на fonts.google.com, выбираете шрифт, добавляете нужные веса. На странице Selected families нажимаете кнопку Download family. Получаете zip с TTF-файлами.
Альтернатива для свободных шрифтов: fontsource.org отдаёт уже готовые WOFF2 для каждого начертания.
Альтернатива для российских проектов: используйте сразу российские шрифты, например, PT Sans от Paratype, или Inter, который технически универсальный, скачанный с GitHub разработчика.
Шаг 2: конвертируйте в WOFF2
В 2026 году поддерживаем только WOFF2. Старые WOFF, EOT, TTF в продакшен не нужны. Все актуальные браузеры понимают WOFF2 много лет.
Конвертация: онлайн через transfonter.org (бесплатно), или локально через pyftsubset из fonttools:
pip install fonttools brotli
pyftsubset Inter-Regular.ttf
--output-file=Inter-Regular.woff2
--flavor=woff2
--layout-features='*'
--unicodes='U+0020-007E,U+0400-045F,U+0490-0491'
Параметр --unicodes это subsetting. Указано: ASCII (латиница), кириллица, плюс несколько украинских символов. Если сайт международный, добавьте нужные диапазоны.
После такой команды файл Inter-Regular.woff2 весит обычно 30-50 КБ. Без subsetting тот же файл был бы 120-180 КБ.
Шаг 3: подключите в CSS
Кладёте файлы в /fonts/ и пишете в CSS:
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Inter';
src: url('/fonts/Inter-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
}
В font-family после кастомного указываете системные fallback. Если шрифт не загрузился или браузер с optional не дождался, текст рисуется системным.
Шаг 4: preload критичного шрифта
Чтобы браузер начал грузить шрифт раньше, чем дойдёт до CSS, ставьте <link rel="preload">:
<link rel="preload"
href="/fonts/Inter-Regular.woff2"
as="font"
type="font/woff2"
crossorigin>
crossorigin обязателен для шрифтов, иначе preload не сработает корректно, и шрифт всё равно загрузится поздно.
Preload делайте только для тех 1-2 шрифтов, которые используются на первом экране. Если preload-ите все шесть начертаний, теряете смысл.
Шаг 5: не подменяйте шрифт через размер
Когда системный fallback заменяется на кастомный, ширина символов меняется, и текст перерисовывается. Это даёт CLS.
Лечение: подбираем метрики системного fallback так, чтобы он занимал ровно столько же места, что кастомный. Делается через свойства size-adjust, ascent-override, descent-override, line-gap-override:
@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 (npm) или capsize делает это автоматически: говоришь, какой системный шрифт ты хочешь использовать как fallback, и она генерирует правильный @font-face.
С этим приёмом подмена шрифта на странице остаётся незаметной, CLS не растёт, и можно безопасно использовать font-display: swap.

Variable Fonts: один файл вместо десяти
Variable Fonts (VF) это шрифт, в котором все начертания и веса упакованы в один файл. Один WOFF2 размером 80-150 КБ покрывает всю гамму от тонкого до жирного, прямого и наклонного.
Плюсы: меньше HTTP-запросов, удобнее использовать промежуточные веса (например, font-weight: 550 для подзаголовков).
Минусы: один файл больше, чем отдельный обычный, поэтому если вы используете только два веса (regular + bold), variable может оказаться чуть медленнее. Но если у вас 4-5 разных весов, variable однозначно лучше.
Подключение через тот же @font-face с диапазоном весов:
@font-face {
font-family: 'Inter Variable';
src: url('/fonts/Inter.var.woff2') format('woff2-variations');
font-weight: 100 900;
font-style: normal;
font-display: swap;
}
В font-weight указываете диапазон, в котором живёт шрифт. Дальше в CSS можно ставить любые значения в этом диапазоне.
Многие популярные шрифты имеют variable-версии: Inter, Roboto Flex, Manrope, Source Sans, JetBrains Mono. Скачивать удобно с fontsource.org или с GitHub автора.
В большинстве моих новых проектов на Astro я использую @fontsource-variable/manrope или @fontsource-variable/inter. Один импорт в BaseLayout, никаких внешних запросов, размер около 80 КБ.
Особые случаи на популярных движках
WordPress
Из коробки многие темы тянут Google Fonts. Лечение зависит от темы.
Если тема использует API Google Fonts через wp_enqueue_style, в functions.php (либо в child-теме) убираете подключение и вместо него регистрируете локальный CSS со своими @font-face. Не забываете снять preload-теги, которые тема добавляет автоматически.
Плагины: OMGF (Optimize My Google Fonts) перехватывает все запросы к fonts.googleapis.com и автоматически качает шрифты в локальную папку. Удобно для случаев, когда тема и плагины массово подключают Google Fonts, и руками править все источники долго.
Альтернатива: плагин Disable and Remove Google Fonts отключает запросы, но не подгружает локальные шрифты, нужно подставить свои.
Tilda
Tilda по умолчанию использует свои шрифты с Tilda CDN. Это работает быстрее, чем Google Fonts CDN в России, но всё же сторонний домен.
Если хотите свой шрифт, в Настройки сайта > Шрифты указываете кастомный шрифт через CSS-код, в котором лежит @font-face со ссылкой на ваш WOFF2. Файл шрифта можно загрузить в Tilda Files или хостить на своём домене.
Минус: в Tilda без премиум-тарифа нельзя править глобальный <head>, поэтому возможности ограничены.
Битрикс
В коробке Битрикса с шрифтами обычно проще: они подключаются либо локально из шаблона, либо через BitrixMainUIExtension. Перенос на self-hosted делается через подмену CSS в шаблоне.
Astro и SSG
В Astro я использую @fontsource-variable/<имя> пакеты с npm. Импорт в BaseLayout:
---
import '@fontsource-variable/manrope';
---
Шрифт автоматически копируется в билд, прописывается в CSS, готов к использованию. Никаких внешних запросов, всё локально.
Аналогично в Next.js через next/font/google (с localhost пакетами) или через ручное скачивание в public/fonts/.
Замер до и после: что должно поменяться
Минимальный набор замеров:
PageSpeed Insights, метрика LCP. Если LCP-элемент это текст с веб-шрифтом, после правильной настройки ожидаем падение на 200-500 мс на мобильном.
PageSpeed Insights, метрика CLS. Если до правок были видны прыжки текста, после правильного fallback и font-display: optional или swap с подобранными метриками CLS снижается.
DevTools Network в Chrome, фильтр по Font. Должно остаться только то, что вы реально подключили, без сторонних доменов.
WebPageTest, waterfall. Шрифт должен начинать грузиться в первой пачке, не после CSS.

Чек-лист настройки шрифтов
- На странице нет запросов к
fonts.googleapis.comиfonts.gstatic.com. - Шрифт лежит локально в
/fonts/в формате WOFF2. - Подключено только нужное количество начертаний (обычно 2-3).
- Используется subsetting под нужные языки.
- В
@font-faceуказанfont-display: swapилиoptional. - Для критичного шрифта стоит
<link rel="preload">сcrossorigin. - Подобраны метрики системного fallback через
size-adjustилиfontaine. - На сайте нет старых WOFF, TTF, EOT, остался только WOFF2.
- В
<head>нет@importсо ссылкой на сторонний шрифт.
После этого шрифты перестанут быть источником тормозов, и про них можно будет забыть на год вперёд.
Когда стоит делегировать
На типичном сайте перевод на self-hosted шрифты занимает 2-5 часов, в зависимости от количества подключений и сложности темы. Это входит в часовую ставку или в любой из тарифов на /#pricing.
Если у вас сайт на WordPress с Google Fonts, плохим LCP и есть подозрение, что виноваты шрифты, опишите ситуацию через /#contact. Связанные материалы по скорости в /blog/category/speed/, там есть статьи про LCP, CLS и виджеты.
Частые вопросы
Почему шрифты тормозят сайт
Потому что браузер по умолчанию ждёт загрузки шрифта и не показывает текст. На медленной мобильной сети это секунда и больше пустого экрана при уже готовой странице.
Как правильно подключать шрифты
Класть файлы на свой хостинг в формате woff2, подключать только нужные начертания и задавать правило, при котором текст рисуется запасным шрифтом сразу, а нужный подменяется по готовности.
Почему не стоит грузить шрифты со стороннего сервиса
Лишнее соединение с чужим доменом добавляет задержку, а для российского сайта ещё и вопрос с передачей данных посетителей за рубеж. Свой хостинг шрифтов снимает обе проблемы.
Сколько начертаний реально нужно
Обычно два-три: обычное, полужирное и курсив, если он действительно используется. Каждое лишнее это отдельный файл, который тоже надо скачать.