Оптимизация шрифтов на сайте: системные шрифты, font-display, предзагрузка и FOIT

Шрифты — самая недооценённая проблема производительности сайта. Неоптимизированный веб-шрифт часто весит от 300 КБ до 2 МБ, и пока он грузится, браузер скрывает текст (FOIT). На 3G это пустой первый экран на 3 секунды...

字体加载四态:FOIT、FOUT、swap与系统字体的取舍Font loading: FOIT vs FOUT vs swap vs system font stack 用Web字体会让首屏文字慢300至1000毫秒 —— B2B站真的值吗Web fonts delay text 300-1000ms — is it worth it on a B2B site 策略Strategy 首屏文字First-paint text 适用判断When to use 系统字体栈System stack 立即显示Instant 大多数B2B站默认选它Default for most B2B font-display:swapfont-display:swap 先fallback后替换Fallback then swap preload+swappreload + swap fallback后快速替换Fast swap after preload 品牌站首屏标题Brand hero headings font-display:blockfont-display:block 3秒内空白(FOIT)3s invisible (FOIT) 核心规则:自定义字体≤2个家族 · 每家族只加载400和700 · 子集化Rule: ≤2 families · weights 400+700 only · subset 中文Web字体几乎不可行 —— 一个中文字体2至8MB,系统字体栈是正确答案CN web fonts impractical (2-8MB) — use system stack 红线:字体文件没子集化就上全站 —— 中文一个文件5MB起步Red line: shipping unsubsetted CJK font (5MB+) font-display:block在3G下等于首屏3秒空白,访客早走了block on 3G = 3s blank screen, visitor already gone
Четыре стратегии загрузки шрифтов: системные шрифты, swap, preload+swap, block — что выбрать

Оптимизация шрифтов на сайте: системные шрифты, font-display, предзагрузка и FOIT

Сначала вывод: Шрифты — самая недооценённая проблема производительности сайта. Неоптимизированный веб-шрифт часто весит от 300 КБ до 2 МБ, и пока он грузится, браузер скрывает текст (FOIT). На 3G это пустой первый экран на 3 секунды. Правильный подход состоит из трёх уровней: на англоязычном сайте — не больше двух семейств веб-шрифтов, в каждом семействе только начертания 400 и 700, обязательно font-display: swap; на китайскоязычном сайте веб-шрифты почти не нужны, используйте системный стек шрифтов, потому что даже один сабсет китайского шрифта весит от 2 до 8 МБ. Контринтуитивный вывод: на B2B-сайте декоративный кастомный шрифт почти не влияет на конверсию, зато тормозит LCP, поэтому системный стек шрифтов — ответ по умолчанию.

1. Почему шрифты блокируют отображение текста

Пока браузер не получил файл шрифта, он не знает, как должен выглядеть текст, и по умолчанию делает его невидимым (FOIT, Flash of Invisible Text). В старых браузерах это скрытие длится 3 секунды, в новых — 1 секунду, после чего принудительно показывается fallback-шрифт. Проблема в том, что текст первого экрана и есть элемент LCP: если он ждёт шрифт, загрузка шрифта затягивает LCP.

Типичная ошибка на сайте: автор темы ради «дизайна» подключает все начертания Inter или Roboto из Google Fonts (от 100 до 900, всего 9 начертаний), каждое по 100 КБ — 900 КБ за одну загрузку. На 3G только шрифты качаются 3–5 секунд, а пользователь видит пустой экран. Метрики Core Web Vitals, связанные со шрифтами, смотрите в Оптимизация Core Web Vitals, а как настроить CDN — в Глобальное ускорение CDN.

Вопрос Влияние на производительность Типичный объём
Загрузка всех начертаний (9 штук) Плюс 800 КБ на первом экране 80–120 КБ на начертание
Китайский шрифт без сабсета 2–8 МБ в одном файле Намного больше бюджета первого экрана
font-display по умолчанию block FOIT скрывает текст на 1–3 секунды Текст не виден
Ключевой шрифт не предзагружен Шрифт обнаруживается поздно, задержка 200 мс LCP замедляется
Больше трёх семейств Каждое семейство нужно скачать В сумме 300–500 КБ

2. Системный стек шрифтов: ответ по умолчанию для B2B-сайта

Системный стек шрифтов (system font stack) использует шрифты, уже установленные на устройстве пользователя: ноль сетевых запросов, мгновенное отображение. Контент B2B-сайта — это в основном таблицы характеристик, описания кейсов и технические статьи; для такой вёрстки не нужны декоративные или брендовые шрифты, системного стека вполне достаточно визуально, и он одинаково выглядит на всех платформах.

Готовый CSS-стек: font-family: -apple-system, BlinkMacSystemFont, “Segoe UI”, Roboto, “Helvetica Neue”, Arial, “PingFang SC”, “Microsoft YaHei”, sans-serif. Он покрывает macOS, Windows, Android и iOS — для латиницы и китайского есть свои системные шрифты. Контринтуитивный вывод:системные шрифты не делают сайт «непрофессиональным», наоборот — GitHub, Stripe и Linear, эти эталоны дизайна, используют системный стек шрифтов. Как выбрать тему WP — см.Технологический стек WordPress.

Подход Текст первого экрана Дополнительная загрузка Тип сайта
Только системные шрифты Показывается сразу 0KB Большинство B2B-сайтов
1 веб-шрифт для заголовков Замена после fallback от 30 до 80KB Сайты с акцентом на бренд
2 семейства веб-шрифтов Замена после fallback 80–150 КБ Брендовые сайты с дизайном во главе
3+ веб-шрифта Заметный FOUT/FOIT >200KB Не рекомендуется
Полный китайский веб-шрифт FOIT на несколько секунд 2–8MB Практически неприменимо

3. font-display:swap и FOIT: не прячьте текст

font-display — свойство внутри @font-face, оно управляет тем, как показывается текст, пока шрифт загружается. Четыре значения: auto (по умолчанию в браузере, раньше это был block), block (текст ненадолго скрывается на 3 секунды, затем fallback), swap (сразу показывается fallback, а когда шрифт загрузится — заменяется), optional (браузер решает сам и склоняется к тому, чтобы не загружать шрифт).

Для B2B-сайтов всегда используйте swap. На 3G-сети block означает пустой первый экран на 3 секунды — посетитель уже уйдёт; optional подходит для шрифтов, не критичных для бренда, но он непредсказуем. Частое заблуждение — «swap вызывает мерцание шрифта (FOUT)», но для B2B-сайта важнее, чтобы пользователь сразу прочитал характеристики и контакты, чем ждал декоративный заголовок. Мерцание шрифта вполне допустимо, а вот невидимый текст — реальная потеря. О стратегии загрузки CSS/JS — см.Оптимизация CSS/JS.

font-display Период блокировки После загрузки шрифта Когда подходит
auto/block Текст невидим до 3 секунд Замена на веб-шрифт Не рекомендуется
swap Сразу показывается fallback Замена, когда шрифт загружен По умолчанию для B2B-сайтов
fallback Скрытие на 100ms, затем fallback Замена, только если загрузился за 3 секунды Полукритичные шрифты
optional Скрытие на 100ms, затем fallback В этот визит замены не будет Чисто декоративные шрифты

4. preload и сабсеттинг: ускоряем то, что должно быть быстрым

Если заголовок первого экрана обязательно должен быть веб-шрифтом, используйте preload, чтобы браузер скачал его заранее с высоким приоритетом: добавьте в head <link rel=”preload” href=”font.woff2″ as=”font” type=”font/woff2″ crossorigin>. Тогда шрифт начнёт загружаться ещё до разбора CSS, и LCP выиграет 200–400 миллисекунд. Учтите: атрибут crossorigin опускать нельзя, иначе preload не сработает.

Субсеттинг (subset) — ещё одна обязательная оптимизация. Для английских шрифтов оставляем только латиницу, цифры и частые символы — размер падает со 100 КБ до 30 КБ. Для китайских шрифтов набор символов настолько велик, что даже после субсеттинга остаётся от 200 КБ до 1 МБ, поэтому для китайских сайтов и советуют сразу системные шрифты. С помощью glyphhanger или параметра text в Google Fonts загружайте только используемые символы. Конкретный пример: в заголовке первого экрана всего 20 иероглифов — субсеттим только их, и файл сжимается с 4 МБ до 5 КБ. Кэширование в CDN — см.Сравнение вариантов CDN.

Действие по оптимизации шрифтов Выигрыш по размеру и задержке Сложность внедрения Рекомендация
Только формат woff2 На 30% меньше, чем ttf Низкая Обязательно
Загружать только начертания 400 и 700 Скачивание меньше на 60% Низкая Обязательно
Субсеттинг английского набора символов Ещё минус 50% Средний Рекомендуется
preload шрифта первого экрана LCP раньше на 200–400 мс Низкая Для заголовка первого экрана использовать
Полный китайский веб-шрифт Минус Высокий Не делать

Пять. Приёмка: смотрим водопад загрузки шрифтов в DevTools

Как проверить, что оптимизация шрифтов сделана? Откройте панель Network в Chrome DevTools, отфильтруйте Font и посмотрите на три вещи: количество файлов шрифтов (должно быть ≤2 семейства, ≤2 начертания на семейство), размер файлов шрифтов (здоровый показатель — ≤50 КБ на файл) и момент начала скачивания (после preload они должны быть среди самых первых запросов, а не обнаруживаться после разбора CSS). Если какой-то файл шрифта больше 100 КБ, стоит вернуться и проверить, не ошибка ли это в начертаниях или субсеттинге.

Затем в Lighthouse посмотрите два аудита: «Avoid layout shifts from web fonts» и «Preload key requests». Вот выполнимый чек-лист: у всех font-display стоит swap, шрифт первого экрана в preload, формат woff2, нет старых форматов ttf/eot, в Google Fonts используется параметр display=swap. Как работать со шрифтами на многоязычных сайтах — см.Работа с графиками на многоязычном сайте. Мониторинг сайта — см.Оповещения мониторинга сайта.

Пункт приёмки Критерий нормы Инструмент измерения
font-display Везде swap или fallback Проверка CSS
preload шрифта первого экрана Шрифт заголовка первого экрана в preload DevTools Network
Формат файлов шрифтов Только woff2 Фильтр Font в Network
Размер одного шрифта ≤50 КБ Столбец Size в Network
Количество семейств шрифтов ≤2 Проверка CSS
75-й процентиль LCP ≤2,5 секунды CrUX/RUM

FAQ: частые вопросы

Обязательно ли использовать веб-шрифты на отдельном B2B-сайте?
Нет, системный стек шрифтов — правильный ответ для большинства B2B-сайтов. Контент B2B — это в основном характеристики, кейсы и технические статьи, и системные шрифты визуально вполне справляются, а благодаря нулевым сетевым запросам текст показывается сразу. GitHub, Stripe и Linear используют системный стек шрифтов. Только когда бренд особенно важен и для заголовка первого экрана нужен особый шрифт, загружайте одно семейство веб-шрифтов, и обязательно с swap + subset + preload.
Чем font-display:swap отличается от block?
block скрывает текст на время загрузки шрифта (FOIT) и только через 3 секунды переключается на fallback; swap сразу показывает текст запасным шрифтом, а после загрузки веб-шрифта заменяет его. Для B2B-сайтов обязателен swap, потому что важнее дать пользователю прочитать контент, чем ждать декоративный заголовок. На сети 3G block означает пустой первый экран на 3 секунды — посетитель давно уйдёт. fallback — компромисс: скрывает текст на 100 мс, затем показывает запасным шрифтом и заменяет, только если веб-шрифт загрузится за 3 секунды.
Можно ли использовать веб-шрифты для китайского?
Практически не стоит. Китайские шрифты весят 2–8 МБ, а после сабсеттинга всё равно 200 КБ–1 МБ — это намного больше бюджета первого экрана. Даже с сабсетом при переходе на страницу со знаками вне набора шрифт придётся загружать заново. Правильный подход — системный стек шрифтов: на macOS PingFang SC, на Windows Microsoft YaHei, на Android Noto Sans CJK. Выглядит одинаково на всех платформах и ничего не скачивается. Картинкой делают только логотип, весь текст — системными шрифтами.
Зачем добавлять crossorigin при preload шрифта?
Потому что шрифт запрашивается по CORS: даже при том же источнике нужен атрибут crossorigin, иначе preload скачает файл, но @font-face его не использует — ресурс потрачен впустую. Правильная запись: link rel=preload as=font type=font/woff2 href=… crossorigin. Пропущенный crossorigin — самая частая причина, почему preload не работает; Lighthouse выдаёт «Предзагруженный ресурс не использован».
Как загрузить Google Fonts быстрее всего?
Три шага. Первый: добавьте в URL параметр display=swap. Второй: запрашивайте только начертания 400 и 700, а не все подряд. Третий: разместите файлы шрифтов у себя, не ссылайтесь на fonts.googleapis.com. Домен Google Fonts блокируется или работает медленно в Китае и в части корпоративных сетей Европы и США; при self-hosting шрифты идут через ваш CDN и экономится ещё одно DNS-соединение. Скачайте woff2 локально через Google Webfonts Helper.
Как принять работу после оптимизации шрифтов?
В DevTools отфильтруйте Network по Font и проверьте три вещи: семейств шрифтов не больше двух, один файл не больше 50 КБ, шрифты первого экрана — среди самых ранних запросов. В CSS посмотрите, что у всех font-display стоит swap и нет старых форматов ttf/eot. В Lighthouse проверьте, что оба аудита — «Избегайте сдвигов макета» и «Предзагрузка ключевых запросов» — зелёные. В конце по CrUX посмотрите, укладывается ли 75-й процентиль LCP в 2,5 секунды. Если LCP всё ещё медленный, откройте панель Performance и проверьте, не блокирует ли его шрифт.

Шесть. FOUT и сдвиг макета: как избежать прыжков при смене шрифта

При стратегии swap подмена fallback-шрифта на веб-шрифт может сдвинуть страницу: ширина и высота знаков различаются — отсюда и берётся CLS (совокупный сдвиг макета). Stripe измеряла это: одна подмена шрифта даёт в среднем 0,05–0,1 CLS, то есть ровно на границе нормы 0,1. На B2B-сайтах текст длинный, абзацев много, и из-за разницы в переносах строк картинки прыгают вверх-вниз.

Решают два дескриптора: font-size-adjust и size-adjust. В @font-face задайте size-adjust: 105% и ascent-override, чтобы метрики веб-шрифта были близки к fallback, — тогда при подмене почти ничего не прыгает. Ещё проще подобрать пару, где метрики fallback и веб-шрифта близки: например, для Inter взять fallback Arial или вообще не менять системный стек шрифтов. Конкретная проверка: в Lighthouse посмотрите аудит «Избегайте сдвигов макета при использовании веб-шрифтов». Если оценка низкая, сначала выясните, не из-за swap ли это, и только потом решайте, добавлять ли size-adjust.

Как работать с FOUT Улучшение CLS Сложность внедрения
Не трогать, смириться с мерцанием от 0,05 до 0,1 Нет
Тонкая настройка метрик через size-adjust Снизить до 0,02 и ниже Средний, нужно тестировать
Выбрать fallback с близкими метриками Снизить до 0,03 и ниже Низкая
Просто отказаться от Web-шрифтов 0 Ноль затрат

В заключение

Главный принцип оптимизации шрифтов прост: пользователи B2B-сайта приходят читать характеристики, смотреть кейсы и искать контакты, а не любоваться типографикой. Системный стек шрифтов — правильный ответ в 95% случаев: сэкономленные сотни килобайт и сотни миллисекунд важнее визуальной разницы. Даже если оставляете Web-шрифты, держитесь четырёх рамок: два семейства, два начертания, формат woff2, загрузка swap.

Три шага на практике. Первый: на этой неделе переведите шрифты темы на системный стек и удалите лишние подключения Google Fonts. Второй: всем оставленным Web-шрифтам добавьте font-display:swap, оставьте только начертания 400 и 700, разместите файлы woff2 на своём сервере. Третий: для шрифта заголовка первого экрана добавьте preload и пропишите crossorigin. Через две недели проверьте, улучшились ли LCP и аудиты, связанные со шрифтами.

Фраза, которую стоит запомнить: пользователь не задержится на секунду дольше из-за того, что на вашем сайте стоит Inter, но закроет вкладку, если будет три секунды ждать загрузки шрифта. Шрифт — это деталь, но именно от деталей зависит, удержите ли вы внимание в те самые 2,5 секунды первого экрана.

crater
crater Эксперт Crater

Официальный аккаунт организации · crater Crater

环形山 (Crater) — компания, которая помогает выходить на зарубежные рынки: разработка сайтов на WordPress, Google SEO и комплексный рост в GEO. Мы работаем с умными устройствами, промышленным оборудованием, SaaS и новой энергетикой.

Возможности продуктаБелая книга по методологииОтраслевые отчёты
965篇分享
78статей в базе знаний