Быстродействие сайтаТехническое SEO

Первый экран прыгает: как мы искали сдвиг от шрифта и что не сработало

17.08.2026 аудит показал CLS 0,2283 на десктопной главной нашего сайта. Причиной оказался шрифт: единица ch в абзаце и наклоненная декоративная полоса. Разбираем, какие советы по замерам не помогли, что дало 0,0056 и как проверить свой сайт.

17 августа 2026 года мы прогоняли SEO-аудит собственного сайта. По скорости главная выглядела хорошо: на десктопе 1920×1080 первый контент появлялся за 820 мс. Но в той же строке отчета стоял CLS 0,2283, то есть суммарный сдвиг макета первого экрана. Мобильный прогон (390×844) в тот же день показал 0,0000.

Напомним пороги: до 0,1 считается «хорошо», выше 0,25 — «плохо». Значит, 0,2283 формально лишь «требует улучшения», но до плохой зоны оставалось совсем немного. Повторные прогоны в рамках того же аудита дали 0,2284, так что случайным совпадением это не было.

Ниже рассказываем, как мы искали причину, какие распространенные советы по замерам не помогли и как проверить то же самое на своем сайте. Сразу о границах: все лабораторные цифры сняты на главной странице нашего сайта в Chromium при 1920×1080. На другом шаблоне и с другими шрифтами числа будут свои, а вот способ поиска подойдет. Стартовые 0,2283 аудит снял на живом сайте через сеть, а 0,0056 и замеры 3 сентября — на локальной продакшн-сборке, без сетевой задержки до сайта.

Что именно прыгало

Аудит записал один скачок на 739–777 мс после старта загрузки. Правый блок первого экрана, где заголовок и абзац, проседал по высоте с 507 до 468 px. Вместе с ним на 39 px подтягивалось все, что стояло ниже.

Причина скачка — подмена шрифта. Страница сначала рисуется резервным системным шрифтом, а когда догрузится фирменный, браузер перерисовывает текст (font-display: swap). У этих шрифтов разные метрики: высота строки, ширина букв. Из-за этого текст занимает другое место, и соседние блоки сдвигаются.

Почему этого никто не заметил

Первая причина: на телефоне сдвига не было, а главную почти все проверяют именно с телефона.

Вторая причина — полевые данные. За 28 дней до 7 сентября PostHog показал p75 CLS ровно 0 и на мобильных (40 замеров), и на десктопе (24 замера). Учитывались только посетители, которые согласились на cookie. Выборка мала, и большая часть этого окна приходится на время до исправлений. То есть в полевых данных проблема просто не проявилась. Наше предположение (отдельно мы его не измеряли): при повторном визите шрифт уже лежит в кеше браузера и успевает до первой отрисовки, поэтому подмены нет.

Третья причина: скачок длится долю секунды. Разработчик с «теплым» кешем его не видит.

Шаг 1: метрики резервного шрифта (17.08)

В тот же день мы сделали очевидное: добавили резервный @font-face с вертикальными метриками, которые взяли из самого файла шрифта, а не по памяти (ascent-override, descent-override, line-gap-override).

Повторный покадровый замер показал, что этого мало: блок первого экрана все равно проседал с 511 до 468 px. Высоту строки мы выровняли, а скачок от этого почти не изменился.

Шаг 2: единица ch (03.09)

Вторая причина нашлась в одном классе. У абзаца было ограничение ширины max-width: 40ch. Единица ch — это ширина глифа «0» в шрифте, который активен именно сейчас. Так что пока текст набран резервным шрифтом, ширина одна, а после подмены уже другая.

Вот что показал покадровый замер:

Момент max-width Высота абзаца Строк
915 мс 360 px 112,2 px 4
938 мс 400 px 84,1 px 3

Контейнер становился на 40 px шире, абзац терял строку, и блок съезжал. Мы заменили 40ch на фиксированные 400px: в фирменном шрифте это та же ширина, так что длина строки для читателя не изменилась. После этого блок менялся уже с 483 до 468 px, а не с 511. Остаточный CLS составил 0,0640, это уже зеленая зона. Однако мы хотели понять, что держит и этот остаток.

Шаг 3: наклоненная декоративная полоса

Остаток давала декоративная полоса с контурными словами, наклоненная через skew. У наклоненного элемента высота рамки равна высоте строки плюс ширина слова, умноженная на тангенс угла. Поэтому любое изменение ширины текста превращается в изменение высоты. Во время подмены шрифта три слова полосы изменили высоту так: 207→212, 203→199 и 179→186 px. По площади сдвига полоса перевешивала весь текст первого экрана.

Мы также поставили контрольный опыт: полностью заблокировали файлы шрифтов. CLS стал ровно 0,0000, значит, сдвиг на 100 % вызывал шрифт и ничего другого искать не нужно было.

Дальше мы проверили стандартные советы. Каждый проверяли замером, а не на глаз:

Что пробовали CLS
size-adjust в резервном шрифте 0,0640 — без изменений
высота строки в пикселях 0,0640 — без изменений
font-display: block 0,0930 — хуже
font-display: optional + preload 0,0056

size-adjust выравнивает среднюю ширину строки, а на конкретных словах заглавными буквами погрешность остается. Высота строки в пикселях не помогает, потому что наклон снова добавляет ширину к высоте. С block вышло самое интересное: пока шрифт грузится, текст невидим, но место под него браузер считает по резервному шрифту. Когда шрифт приходит, подмена все равно происходит.

Сработал font-display: optional. Браузер ждет шрифт около 100 мс, и если тот не успел, резервный остается до конца загрузки страницы, без подмены. Но сам по себе он испортил бы дизайн: шрифт почти никогда не успевал, и полоса рисовалась бы резервным Arial. Измеренная ширина полосы тогда 839 px вместо фирменных 753. Поэтому мы добавили <link rel="preload"> на файл шрифта, чтобы он начинал грузиться вместе с HTML, а не после разбора CSS. С этим полоса по замеру имеет фирменные 753 px, а сдвига нет.

Окончательный замер: три прогона, локальная продакшн-сборка, 3 сентября. На десктопе CLS 0,0056 при LCP 876 мс, на мобильном CLS 0,0000 при LCP 768 мс.

optional мы дали только декоративной полосе. Основному тексту так делать нельзя: читатель видел бы то один шрифт, то другой в зависимости от скорости сети.

Чего стоило исправление и что нашлось заодно (07.09)

Preload оказался не бесплатным. Через 4 дня PageSpeed на мобильном назвал крупнейшим элементом первого экрана (LCP) именно эту полосу. А ее шрифт, полный файл на 22 КБ, прелоадился на каждой странице сайта. Полосе нужны лишь 17 глифов, так что мы вырезали из того же файла подмножество на 2,8 КБ.

Во время того же разбора в сетевых запросах нашлись еще два шрифта, 58 и 57 КБ. Они грузились на каждой странице, хотя ни один стиль сайта их не использовал: пакет оставался подключенным в корневом шаблоне, хотя его переменные никто не читал. Мы убрали импорт и проверили, что вид текста не изменился.

Как проверить свой сайт за 15 минут

Вам понадобится Chrome и десктопное окно. Мобильный режим проверьте отдельно: у нас проблема была только на одном из двух.

  1. Откройте DevTools, вкладку Network, включите Disable cache. Так вы увидите страницу глазами нового посетителя.
  2. Перейдите в Performance и запишите перезагрузку. На дорожке Layout shifts будет каждый сдвиг и элементы, которые двигались. Можно обойтись и консолью, вставив после загрузки:
new PerformanceObserver(list => {
  for (const e of list.getEntries()) {
    if (!e.hadRecentInput) console.log(e.value.toFixed(4), e.sources.map(s => s.node));
  }
}).observe({ type: 'layout-shift', buffered: true });
  1. Проведите контрольный опыт. В Network щелкните правой кнопкой на файле шрифта → Block request URL (или задайте шаблон *.woff2 в Request blocking) и перезагрузите страницу. Если сдвиг исчез, виноват шрифт, и картинки с баннерами можно не трогать.
  2. Поставьте фильтр Font в Network и выпишите все файлы шрифтов. Затем в Elements → Computed посмотрите Rendered Fonts на нескольких текстовых блоках. Файл, которого нет среди реально используемых шрифтов, — кандидат на удаление.
  3. Поищите в стилях первого экрана единицу ch в ширинах, а также skew или rotate на блоках с текстом. Обе вещи превращают смену шрифта в изменение размера.

Мы измеряли только собственный сайт на Next.js со шрифтами на своем сервере. В теме OpenCart с Google Fonts механизм подмены тот же, но цифр для такого случая у нас нет.

Чего эти цифры не означают

  • 0,0056 — это лабораторный замер на локальной сборке, а не обещание для каждого посетителя. Сеть, кеш и устройство меняют картину.
  • Ноль в полевых данных мы не можем записать на счет исправлений: большая часть окна приходится на время до них.
  • 12 сентября основные шрифты сайта изменились. Резервные метрики для новых шрифтов считались тем же методом, но повторного покадрового замера первого экрана для этой статьи мы не делали. Все цифры выше относятся к сайту до этого изменения.
  • CLS — одна из метрик Core Web Vitals. Стабильный первый экран убирает технический изъян, а не поднимает позиции сам по себе.

Как мы разбираем остальные метрики, описано в разделе о Core Web Vitals, а о сервере и весе страниц — в статье о скорости сайта для бизнеса. Если на вашем сайте первый экран прыгает, а причина неочевидна, посмотрите, как мы работаем с ускорением сайта.

Теги

PerformanceSEO

Вам понравилась статья?

Ваше мнение помогает нам создавать лучший контент

Поделитесь с друзьями

Нашли что-нибудь полезное?

Помогите другим узнать это — поделитесь статьей в социальных сетях

Спасибо, что помогаете нам расти

Основатель LIONEX

Владислав Чистяков

Пишет о том, что делает руками: интернет-магазины на OpenCart, приложения на Next.js, интеграции и скорость сайтов. В статьях — замеры и проверки, которые читатель может повторить на своём проекте, а не общие советы. Коммерческая разработка с 2015 года.

Вопросы

Частые вопросы

Ответы на популярные вопросы по теме

Что такое CLS и какое значение считается нормальным?

CLS — суммарный сдвиг макета: насколько блоки страницы прыгают во время загрузки. До 0,1 считается «хорошо», выше 0,25 — «плохо». На нашей десктопной главной 17 августа 2026 года аудит показал 0,2283, то есть «требует улучшения», почти вплотную к плохой зоне.

Как понять, что сдвиг вызывает именно шрифт?

Поставьте контрольный опыт: в Chrome DevTools заблокируйте файлы шрифтов (Request blocking, шаблон *.woff2) и перезагрузите страницу с отключенным кешем. У нас после блокировки CLS стал ровно 0,0000. Если у вас сдвиг исчез так же, виноват шрифт, и картинки с баннерами можно не трогать.

Почему не помог font-display: block?

Пока шрифт грузится, текст невидим, но место под него браузер считает по резервному шрифту. Когда фирменный шрифт приходит, подмена все равно происходит. На нашей главной CLS от этого ухудшился: 0,0930 против 0,0640.

Можно ли просто поставить font-display: optional для всего сайта?

Мы так не делали. Для основного текста это плохо: в зависимости от скорости сети читатель видел бы то фирменный шрифт, то резервный. optional мы дали только декоративной полосе и добавили preload ее шрифта, чтобы он успевал до первой отрисовки. Иначе полоса почти всегда рисовалась бы Arial.

Поднимутся ли позиции в Google, если убрать сдвиг?

Этого мы не обещаем. CLS — одна из метрик Core Web Vitals, и стабильный первый экран убирает технический изъян. Но позиции зависят от многих других вещей. К тому же 0,0056 у нас — лабораторный замер на локальной сборке, а не гарантия для каждого посетителя.

Получайте лучшие статьи на почту

Подпишитесь на нашу рассылку и получайте полезные советы, инсайты и новости о веб-разработке, маркетинге и бизнесе.

Мы уважаем вашу конфиденциальность. Отписаться можно в любой момент.

Ещё в блоге

Похожие статьи

Пассажиры каждой страницы: словарь целого языка, вторая шапка и чат, которого не просилиБыстродействие сайта

Пассажиры каждой страницы: словарь целого языка, вторая шапка и чат, которого не просили

5 сентября 2026 мы разобрали ответ собственного сайта строка за строкой и нашли пять вещей, которые ехали в браузер каждому посетителю, хотя ими никто не пользовался. 13 сентября нашлась шестая. Показываем байты до и после, урок о символах против байтов и пять проверок для своего сайта.

Читать дальше
Мы потеряли собственный магазин вместе с доменом: что об этом знает веб-архивТехническое SEO

Мы потеряли собственный магазин вместе с доменом: что об этом знает веб-архив

17 сентября 2026 мы пересчитали по веб-архиву, как выглядела потеря собственного магазина вместе с доменом: 2 378 снимков главной в марте 2022, первый 301 первого апреля, последний снимок нашего содержимого 18 мая. Показываем, что из архива восстанавливается, а что нет.

Читать дальше
Почему страница думала три секунды: запрос, которого не видно в коде страницыБыстродействие сайта

Почему страница думала три секунды: запрос, которого не видно в коде страницы

16 августа 2026 года наш сайт отвечал за 3,05 с, а соседи на том же сервере — за 0,2–0,3 с. Виноват запрос мега-меню, который на каждой странице тянул 4,3 МБ переводов. Разбираем его и ещё три похожих случая, а также как найти такое на своём сайте.

Читать дальше