Как исправить CLS и убрать сдвиги макета на сайте
Практика3 минРедакция Innovialabs
Коротко
CLS растёт, когда элементы появляются без заранее зарезервированного места. Задайте размеры медиа и слотов, не вставляйте контент поверх уже показанного и настройте загрузку шрифтов.
Что такое CLS и почему он растёт
CLS (Cumulative Layout Shift) — метрика Core Web Vitals, которая показывает, насколько сильно контент «прыгает» во время работы со страницей. Пользователь хочет нажать на кнопку, а над ней внезапно появляется баннер — и клик уходит не туда. Хорошим значением Google считает 0,1 и ниже.
Почти все сдвиги имеют одну причину: браузер не знает размер элемента заранее. Он рисует страницу, потом догружается картинка, реклама или шрифт — и всё, что ниже, съезжает.
Важно: сдвиги в течение короткого времени после действия пользователя (клик, ввод) не учитываются. Раскрытие аккордеона по клику — это нормально. Плохо, когда страница двигается сама.
Как найти элементы, которые сдвигаются
- PageSpeed Insights — покажет полевые данные (от реальных пользователей Chrome) и лабораторный замер. В разделе диагностики есть список элементов, вызвавших самые большие сдвиги.
- Chrome DevTools → Performance — запишите загрузку, в дорожке Layout Shifts видно каждый сдвиг и элемент.
- Rendering → Layout Shift Regions — в DevTools подсвечивает области сдвига синим прямо на странице.
- Search Console → Core Web Vitals — показывает группы URL с проблемой по данным реальных пользователей.
Проверяйте и мобильную, и десктопную версию: на мобильных сдвиги обычно сильнее из-за узкой ширины.
Основные причины и как их исправить
Картинки и видео без размеров
Самая частая причина. Указывайте width и height — современные браузеры сами вычислят пропорции и зарезервируют место до загрузки.
<img src="/photo.jpg" width="1200" height="800" alt="Офис компании">
Для адаптивных блоков используйте CSS aspect-ratio:
.video-wrapper { aspect-ratio: 16 / 9; width: 100%; }
Рекламные слоты и встраивания
Реклама, карты, видео с YouTube, виджеты соцсетей загружаются поздно и часто без известной высоты.
- Задайте контейнеру min-height под самый частый размер объявления.
- Не схлопывайте слот, если реклама не пришла, — лучше оставить пустое место или заглушку.
- Для встраиваний используйте фасад: статичное превью нужного размера, а сам iframe грузите по клику.
Веб-шрифты
Когда системный шрифт заменяется на загруженный, меняется ширина строк, и текст переносится по-другому.
- Подгружайте ключевые шрифты заранее через
<link rel="preload">. - Используйте
font-display: optionalдля второстепенных шрифтов илиswapвместе с подобранным запасным шрифтом. - Выравнивайте метрики запасного шрифта через
size-adjust,ascent-overrideв@font-face— тогда подмена почти незаметна. - Хостите шрифты у себя и используйте только нужные начертания.
Баннеры, уведомления и cookie-плашки
Блок, который JavaScript вставляет вверху страницы после загрузки, сдвигает весь контент.
- Показывайте такие элементы поверх контента (
position: fixed), а не в потоке документа. - Если блок должен быть в потоке, зарезервируйте под него место в HTML с самого начала.
- Не вставляйте новый контент над тем, что пользователь уже видит.
Анимации
Анимируйте transform и opacity, а не top, height или margin. Изменение свойств геометрии вызывает перерасчёт макета и может засчитываться как сдвиг.
Чек-лист перед выкладкой
- У всех
img,video,iframeесть размеры илиaspect-ratio. - Рекламные и динамические блоки имеют
min-height. - Шрифты подгружаются заранее, запасной шрифт подогнан по метрикам.
- Баннеры и попапы не толкают контент вниз.
- Скелетоны совпадают по высоте с реальным контентом.
- Страница проверена на мобильном разрешении.
Частые ошибки
- Проверять только в лаборатории. Lighthouse измеряет загрузку, а реальные сдвиги часто случаются при прокрутке и подгрузке ленты.
- Lazy-load без размеров. Ленивая загрузка картинок без
width/heightгарантирует сдвиг при прокрутке. - Скелетон не той высоты. Заглушка на 200px, вместо которой приходит блок на 400px, — тот же сдвиг.