Веб-шрифты ломают вёрстку: где именно возникает сдвиг
Сдвиг макета от веб-шрифтов почти никогда не связан с самим файлом гарнитуры — он возникает в момент подмены шрифта. Пока браузер скачивает начертание, он либо прячет текст (невидимый текст), либо сразу рисует системным запасным вариантом, а затем перерисовывает загруженным. У этих двух гарнитур разная ширина знаков, высота строки и метрики, поэтому абзац, свёрстанный под одну, при подмене шрифта переразбивается на другое число строк.
Дальше срабатывает цепная реакция. Строка, которая была одной, становится двумя — весь контент ниже сдвигается вниз. Кнопки, поля формы, блоки с фиксированной высотой и прилипшая навигация прыгают на десятки пикселей, а пользователь в этот момент уже начал читать или целиться в элемент. Показатель сдвига макета фиксирует каждое такое смещение как отдельное событие, и именно шрифтовая подмена даёт львиную долю этих событий на типичной странице.
Отдельный случай — невидимый текст. Если период скрытия выставлен слишком долго, пользователь видит пустые блоки вместо заголовка, а затем резкий скачок строк, когда гарнитура наконец подгрузилась. Это хуже, чем мгновенный показ запасным шрифтом: страница выглядит сломанной ровно в тот момент, когда посетитель решает, оставаться ли на ней.
Корень проблемы — в рассинхроне: браузер не знает метрик ещё не загруженного начертания и не может заранее зарезервировать место. Значит, закрывать это нужно на уровне настройки загрузки и описания метрик, а не подбором «похожего» шрифта на глаз. Разбираем, как это устроено и что именно настраивается.
Что даёт управляемая загрузка шрифтов
Управляемая загрузка шрифтов — это когда мы заранее решаем, что браузер покажет в первые миллисекунды и как подменит начертание, когда файл догрузится. Без этого решения макет «дышит»: текст отрисовался системным шрифтом, затем подменился веб-шрифтом с другими метриками, и весь блок ниже прыгнул. Ниже — что именно меняется, когда загрузкой управляют осознанно.
- Стабильный макет. Мы подбираем метрики резервного начертания под целевое — совпадают ширина символа, высота строки и положение базовой линии. Подмена происходит без сдвига блоков, показатель скачков макета уходит к нулю.
- Предсказуемая отрисовка первого экрана. Критичные начертания объявляются заранее и грузятся в приоритете, остальные — по мере надобности. Первый экран собирается в одном и том же виде при каждом заходе, а не «как повезёт».
- Отсутствие скачков текста. Для каждого начертания задан свой период подмены: короткий — чтобы не мигал системный шрифт, но достаточный, чтобы не блокировать отрисовку. Текст не перестраивается посреди чтения.
- Устойчивость на медленных каналах. При обрыве или таймауте загрузки браузер остаётся на резервном начертании с теми же метриками — страница читается, вёрстка не рассыпается.
- Предсказуемость на всём парке устройств. Мы проверяем поведение на разных разрешениях, языках и режимах экономии трафика, а не только на своём ноутбуке. Результат — одинаковое поведение текста у всех посетителей.
Эти пункты проверяемы: до и после замеряем сдвиг макета и время до первой отрисовки текста, и разницу видно в цифрах, а не на словах.
Способы подключения шрифтов: сравнение подходов
Выбор способа подключения веб-шрифтов определяет, сколько килобайт критического пути загрузит браузер до первой отрисовки текста, и произойдёт ли сдвиг вёрстки. Ниже — четыре рабочих варианта, между которыми реально выбирают на проектах, с их сильными сторонами и ограничениями.
| Вариант | Когда подходит | Ограничения |
|---|---|---|
| Самохостинг | Брендовый шрифт, стабильный трафик, требования к приватности | Нужно самим готовить подмножество знаков, следить за обновлением файлов и кэш-заголовками |
| Внешний сервис | Быстрый старт, много языков и начертаний, нет времени на подготовку файлов | Зависимость от чужого домена: лишнее DNS-соединение, риск блокировки, ограничения лицензии на самостоятельный хостинг |
| Системный стек | Интерфейсы, админки, контентные блоки, где важен только текст | Нет контроля над внешним видом: на разных платформах гарнитура отличается, брендовая типографика теряется |
| Подмножество знаков | Кириллица + латиница, один-два алфавита, крупные массивы текста | Требует разбивки на диапазоны и проверки, что редкие символы не выпадают в подстановку |
Самохостинг даёт полный контроль: файлы лежат на своём домене, версионируются вместе с релизом, а font-display: swap и предзагрузка ключевого начертания убирают невидимый текст на старте. Ограничение — сопровождение: при обновлении гарнитуры нужно пересобрать подмножество знаков и сбросить кэш, иначе часть пользователей останется на старой версии.
Внешний сервис снимает подготовку файлов и сам отдаёт нужный диапазон под браузер, но добавляет внешний домен в критический путь. Если сервис недоступен или заблокирован, страница отрисуется системным шрифтом — это допустимо как запасной вариант, но не как основной.
Системный стек не грузит ничего: нулевой вес и нулевой сдвиг вёрстки. Его разумно оставлять как финальный запасной вариант в font-family для любого из первых трёх подходов — тогда при сбое загрузки текст всё равно читается сразу.
Как мы настраиваем загрузку: этапы работ
Начинаем с аудита: смотрим, откуда реально грузятся веб-шрифты — свои файлы, внешние каталоги, подключения через сторонние сервисы. Часто на одной странице набирается 4-6 источников, часть из них дублируется, а часть тянет лишние начертания, которые в вёрстке не используются. На этом шаге фиксируем, какие гарнитуры нужны дизайну, а какие остались «на память» с прошлых итераций.
Дальше выстраиваем схему приоритетов: критичные для первого экрана начертания грузятся раньше, декоративные — после основного контента. Ниже — как выглядит процесс целиком.
- Аудит подключений. Собираем все источники шрифтов на страницах, сверяем с макетом и выявляем лишние начертания, дубли и внешние зависимости.
- Схема приоритетов. Определяем, какие гарнитуры нужны для первого экрана, а какие можно подгружать отложенно, и фиксируем это в правилах.
- Настройка загрузки. Прописываем форматы, предзагрузку критичных файлов и запасные варианты, чтобы текст не «прыгал» при подмене шрифта.
- Резервирование места. Задаём метрики запасного шрифта так, чтобы блоки занимали финальный размер до подгрузки — это и убирает сдвиг вёрстки.
- Проверка на реальных условиях. Прогоняем страницы на медленном соединении и мобильных устройствах, замеряем сдвиг макета и скорость отрисовки текста.
- Правки по результатам. Если сдвиг остался, корректируем метрики или набор начертаний и повторяем замер.
- Передача. Отдаём конфигурацию, правила подключения и короткую инструкцию, как добавлять новые гарнитуры без регресса.
После передачи у заказчика остаётся воспроизводимая схема: любой новый шрифт подключается по тем же правилам, а не «как получится». Опишите вашу задачу — вернёмся с оценкой и планом работ.
Что заказчик получает на руки
Комплект собран так, чтобы шрифтовую часть можно было передать любому инженеру или подрядчику и не потерять поведение страницы. Ниже — что именно уходит в репозиторий и в документацию.
- Конфигурации подключения: файлы шрифтов в WOFF2,
@font-faceсfont-display: swap,unicode-rangeпо наборам знаков и preload только для начертаний первого экрана. - Правила подстановки: цепочка
font-familyс системными запасными, метрикиsize-adjustиascent-override, подобранные под основной шрифт, — подмена не сдвигает строки. - Наборы знаков: разделение на латиницу, кириллицу и служебные символы, чтобы браузер не тянул лишний вес на страницах без них.
- Схема загрузки: порядок preload, кэш-заголовки для шрифтовых файлов, поведение при медленной сети и при отключённых веб-шрифтах.
- Документация: какие начертания используются, где лежат исходники, как проверить сдвиг макета после правок.
- Регламент добавления новых начертаний: кто готовит файл, какие проверки проходят вес и метрики, как обновляется конфигурация и кто подтверждает выкатку.
- Чек-лист приёмки: замер сдвига до и после, проверка на мобильных и в режиме экономии трафика.
Такой комплект снимает зависимость от одного человека: правку вносит любой инженер команды, а поведение текста на странице остаётся предсказуемым.
Кейс: устранение сдвига макета на портале услуг
Портал услуг — каталог с личным кабинетом, где пользователь сравнивает тарифы и оформляет заявки. Шрифт подключался через внешний сервис: пять начертаний, весь набор глифов, включая кириллицу и символы, которые на страницах не встречались. Браузер подгружал файлы после разбора разметки, и до их появления текст перерисовывался запасным начертанием с другими метриками.
Замеры до правок: сдвиг макета на карточках тарифов и в шапке кабинета, время до читаемого текста — заметная пауза на мобильных сетях. Хуже всего было на медленных каналах: пользователь начинал читать, и строки «прыгали» под курсором.
Что изменили
Разделили начертания по назначению: два остались для основного текста и заголовков, остальные убрали. Собрали подмножества глифов под реальные языки портала — лишние символы вырезали. Основное начертание предзагрузили с высоким приоритетом, остальные отдали на откуп браузеру с font-display: swap.
Ключевое — метрики. Для запасного начертания задали size-adjust, ascent-override и descent-override через @font-face, чтобы высота строки совпадала с целевым шрифтом. Плюс зарезервировали место под блоки с крупным текстом.
Что стало
Сдвиг макета на ключевых экранах ушёл — метрики совпадают, перерисовка не двигает блоки. Время до читаемого текста сократилось: запасное начертание показывается сразу и не меняет геометрию. Число загружаемых начертаний уменьшилось более чем вдвое, вес шрифтов на первой загрузке — в разы.
В поддержке осталось правило: новое начертание добавляем только после замера метрик и проверки на мобильных. Подход переносим на другие проекты — веб-шрифты перестают быть источником сдвига, когда метрики запасного варианта выставлены заранее.
Чем отличается предзагрузка от отложенной загрузки шрифтов
Предзагрузка — это когда браузер получает указание скачать файл шрифта в первую очередь, ещё до того, как парсер дойдёт до правил, где этот шрифт объявлен. Инженерно это выглядит так: в начале документа стоит ссылка с атрибутом rel="preload", типом ресурса font и обязательным crossorigin — без последнего браузер скачает файл дважды, потому что шрифты всегда запрашиваются в режиме анонимного CORS.
Такой режим оправдан для одного-двух начертаний, которыми набраны заголовок и первый экран: пока идёт разбор разметки, файл уже лежит в кеше, и критичный текст отрисовывается сразу нужной гарнитурой, без подмены системной.
Отложенная загрузка работает наоборот: шрифт объявляется в правилах, но подключается не блокирующе. Браузер сначала рисует текст системным начертанием, а когда файл догрузился — заменяет его. Здесь и рождается сдвиг: метрики системного и целевого шрифта различаются, строка меняет ширину, и весь блок под ней прыгает вниз. Лечится это не отказом от отложенной загрузки, а подгонкой метрик — свойством size-adjust и переопределением ascent-override в правиле @font-face, чтобы запасной шрифт занимал ровно ту же площадь. Тогда подмена происходит без смещения макета.
Выбор между режимами — это выбор между временем до первого показа текста и стабильностью вёрстки. Предзагрузка ускоряет появление нужной гарнитуры, но конкурирует за канал с критичными ресурсами: если предзагрузить пять начертаний, они отберут пропускную способность у стилей и скриптов, и первый экран покажется позже. Отложенная загрузка не тормозит отрисовку, но требует, чтобы запасное начертание было метрически совместимо с целевым.
На практике режимы комбинируют. Основное начертание для первого экрана идёт через предзагрузку, остальные — отложенно, с font-display: swap и подобранными метриками запасного шрифта. Дополнительно шрифты отдаются в формате woff2 и хешируются в имени файла, чтобы кеш не отдавал старую версию после обновления гарнитуры. Итог — критичный текст виден сразу, а сдвиг остаётся в пределах, которые не замечает ни пользователь, ни метрика стабильности макета.
Частые технические сомнения
Шрифты редко живут в вакууме: обычно это внешний сервис, несколько языков и редкие знаки вроде тире, кавычек-ёлочек или символов валют. Ниже — ответы на то, с чем сталкиваемся чаще всего.
У нас уже подключён внешний сервис шрифтов — придётся всё переделывать?
Нет. Внешний сервис отдаёт файлы и стили, но не управляет тем, как браузер их показывает. Мы оставляем подключение, добавляем font-display: swap и метрические фолбэки — временный системный шрифт с подобранными size-adjust и ascent-override, чтобы подмена не сдвигала текст. Дальше решаем по ситуации: если сервис тормозит на первом экране, переносим критичные начертания к себе и отдаём их с долгим кешем, а остальное оставляем как есть.
Как быть с несколькими языками и редкими знаками?
Разбиваем набор по диапазонам символов: латиница, кириллица, иврит, знаки пунктуации — каждый в своём файле с unicode-range. Браузер тянет только те диапазоны, которые реально встретились на странице, поэтому англоязычный посетитель не грузит кириллицу, а редкий знак не тянет за собой весь шрифт. Для символов, которых нет в основном наборе, задаём явный фолбэк в font-family, чтобы вместо «квадратика» подставился системный глиф.
Что будет, если шрифт не загрузится вообще?
Страница останется читаемой: текст покажется системным шрифтом, вёрстка не поедет за счёт метрических фолбэков. Это осознанный выбор в пользу доступности — посетитель видит контент сразу, а начертание подставляется по мере загрузки. Проверяем сценарий отключением сети в инструментах разработчика и сверяем сдвиг макета до и после подмены.
Насколько это сложно поддерживать дальше?
Правила описываются один раз в конфигурации: какие начертания, какие диапазоны, какой кеш. Дальше это часть сборки — при добавлении языка или знака достаточно расширить диапазон, а не переписывать стили. Мы фиксируем метрики до и после, чтобы сдвиг макета оставался нулевым при каждом обновлении.
Обсудим вашу задачу со шрифтами
Чтобы вернуться с оценкой и планом, а не с общими словами, нам нужны вводные по вашему проекту. Шрифтовая тема почти всегда упирается в конкретику: какие гарнитуры уже подключены, откуда грузятся, где именно «прыгает» вёрстка. Чем точнее исходные данные, тем меньше итераций на согласование.
Что прислать для оценки:
- список гарнитур и начертаний, которые используются сейчас, с указанием, где они хостятся;
- ссылку на рабочий сайт или стенд, где воспроизводится проблема со сдвигом контента;
- скриншоты или запись метрик сдвига из панели разработчика на медленном соединении;
- данные о том, какие браузеры и устройства в приоритете по вашей аудитории;
- требования дизайна: какие начертания критичны, какие можно заменить системными;
- ограничения по хостингу, CDN и политике кэширования, если они есть;
- контакт человека, который принимает решения по вёрстке и дизайну.
На выходе вы получите план внедрения: какие гарнитуры оставляем, какие переводим в локальный хостинг, как настраиваем предзагрузку и подмену метрик, какие проверки ставим в сборку. Плюс оценку сроков по этапам и перечень правок, которые нужно внести на стороне дизайна.
Опишите задачу — вернёмся с оценкой и планом.







