Загрузка...
Загрузка...
Практическое руководство по устранению Cumulative Layout Shift. Диагностика причин сдвигов макета, резервирование размеров, оптимизация шрифтов и динамического контента.
Полное руководство по оптимизации Largest Contentful Paint. Причины медленного LCP, методы диагностики, практические решения для изображений, шрифтов и серверной инфраструктуры.
SEOПрактическое руководство по оптимизации INP — метрики отзывчивости интерфейса. Причины задержек, разбиение длинных задач, оптимизация JavaScript и обработчиков событий.
SEOКак оптимизировать анкорный текст внутренних ссылок для SEO. Разнообразие анкоров, передача релевантности, избежание переоптимизации. Практические рекомендации.
SEOРуководство по массовой проверке URL. Сценарии использования, инструменты, интерпретация результатов. Проверка статус-кодов, редиректов и битых ссылок на масштабе.
Поделитесь с коллегами или изучите другие материалы блога
Cumulative Layout Shift (CLS) — метрика Core Web Vitals, измеряющая визуальную стабильность страницы. Каждый неожиданный сдвиг контента при загрузке ухудшает пользовательский опыт: пользователь собирается кликнуть по кнопке, а страница «прыгает» и клик попадает не туда. Google учитывает CLS в ранжировании с 2021 года. В этом руководстве разберём причины сдвигов и практические способы их устранения.
CLS — накопительная метрика. Браузер вычисляет «долю сдвига» для каждого нестабильного элемента: произведение доли viewport, затронутой сдвигом, на расстояние сдвига. Все сдвиги за сессию суммируются.
| Оценка | CLS | Восприятие |
|---|---|---|
| Хорошо | ≤ 0.1 | Стабильная страница |
| Требует улучшения | 0.1 – 0.25 | Заметные сдвиги |
| Плохо | > 0.25 | Сильно раздражает пользователей |
Один крупный сдвиг (например, баннер на 50% экрана) может дать CLS > 0.25. Несколько мелких сдвигов накапливаются.
Проверить CLS можно с помощью инструмента Web Vitals на reChecker.
Самая частая причина. Браузер не знает размеры изображения до загрузки, не резервирует место — при появлении картинки контент ниже сдвигается.
<!-- Плохо: нет размеров -->
<img src="product.jpg" alt="Товар">
<!-- Хорошо: размеры указаны -->
<img src="product.jpg" alt="Товар" width="400" height="400">
Рекламные блоки, виджеты, карты загружаются асинхронно. До загрузки их высота неизвестна — контент сдвигается при появлении.
Вставка контента поверх существующего (уведомления, баннеры cookie, модальные окна) вызывает сдвиг. То же самое — подгрузка контента infinite scroll.
При смене системного шрифта на кастомный (или наоборот) размеры текста меняются. Строки занимают больше или меньше места — макет сдвигается.
Анимации, меняющие размер или позицию элементов, могут учитываться в CLS, если происходят в первые 500 мс после взаимодействия пользователя.
Всегда указывайте размеры для всех изображений:
<img src="hero.jpg" alt="Hero" width="1200" height="630">
В HTML4 width и height задавали физический размер. В современном HTML они задают aspect ratio — браузер резервирует место до загрузки. CSS может масштабировать изображение, но пропорции сохраняются.
Для контейнеров с background-image или динамическим контентом:
.hero {
aspect-ratio: 16 / 9;
background-image: url('hero.jpg');
background-size: cover;
}
<img src="product.jpg" alt="Товар"
width="400" height="400"
style="max-width: 100%; height: auto;">
max-width и height: auto сохраняют пропорции при ресайзе, а width/height задают начальный aspect ratio.
Рекламные сети часто не предоставляют размеры заранее. Варианты:
Фиксированный контейнер:
<div class="ad-container" style="min-height: 250px;">
<script async src="//adnetwork.com/ad.js"></script>
</div>
Reserve space через data-атрибуты (если сеть поддерживает):
<ins class="adsbygoogle"
style="display:block"
data-ad-format="rectangle"
data-ad-slot="123"
data-ad-client="ca-pub-xxx"
data-full-width-responsive="false"></ins>
<div style="position: relative; padding-bottom: 56.25%; height: 0;">
<iframe src="https://www.youtube.com/embed/VIDEO_ID"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
allowfullscreen></iframe>
</div>
padding-bottom: 56.25% создаёт соотношение 16:9. Контейнер резервирует место до загрузки iframe.
Для нефоновых шрифтов — optional отображает текст системным шрифтом и использует кастомный только если он уже загружен. Минимизирует сдвиги, но не всегда подходит для брендинга.
@font-face {
font-family: 'BrandFont';
src: url('/fonts/brand.woff2') format('woff2');
font-display: optional;
}
При swap размеры системного и кастомного шрифта могут отличаться. Используйте размер-ключевые пары (size-adjust) для уменьшения сдвига:
@font-face {
font-family: 'CustomFont';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
size-adjust: 98%; /* Подгонка под системный fallback */
}
Чем раньше загрузится шрифт, тем меньше вероятность сдвига при его применении:
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
Не вставляйте баннер поверх контента. Резервируйте место в layout:
body {
padding-bottom: 60px; /* Высота баннера */
}
.cookie-banner {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 60px;
}
Или показывайте баннер внизу страницы как часть потока документа, а не fixed overlay.
Модальные окна (position: fixed) не вызывают layout shift основного контента — они поверх. Но появление баннера «Подпишитесь» в середине статьи, который сдвигает текст, — да. Используйте фиксированную позицию или резервируйте место.
Для контента, загружаемого асинхронно, используйте skeleton — заглушку с теми же размерами, что и реальный контент:
<div class="card-skeleton" style="width: 300px; height: 200px;">
<div class="skeleton-line" style="height: 20px; margin-bottom: 10px;"></div>
<div class="skeleton-line" style="height: 20px; width: 80%;"></div>
</div>
Когда контент загрузится, замените skeleton — размеры совпадают, сдвига нет.
| Причина | Решение | Сложность |
|---|---|---|
| Изображения без размеров | width, height на все img | Низкая |
| Реклама/embed | min-height или aspect-ratio контейнера | Средняя |
| Шрифты | font-display: swap + size-adjust, preload | Средняя |
| Cookie-баннер | Резервирование места или fixed без сдвига | Низкая |
| Динамический контент | Skeleton, резервирование | Средняя |
| Анимации | Избегать изменения layout в первые 500 мс после input | Низкая |
В Performance записи включите «Experience» → «Layout Shifts» — каждая метка показывает элемент и величину сдвига.
Реклама — частый источник сдвигов. Блоки загружаются асинхронно, размеры неизвестны до загрузки.
Договоритесь с рекламной сетью о фиксированных размерах или используйте контейнер с min-height. Для адаптивных блоков — aspect-ratio или резервная высота по типу формата (320x50, 300x250).
Фиксированный хедер при скролле может вызывать сдвиг при появлении. Резервируйте место в layout (padding-top на body) или используйте position: sticky с учётом начальной высоты.
React, Vue, Angular могут добавлять контент после гидрации. Резервируйте место для skeleton или используйте CSS, предотвращающий сдвиг при появлении контента.
Подгрузка контента при скролле — новые элементы не должны сдвигать уже отображённое. Контейнеры с фиксированной высотой или резервирование под скелетон.
Rendering → Layout Shift Regions. Подсвечивает области сдвига. Performance → Experience → Layout Shifts. Каждый сдвиг с величиной и причиной.
Показывает CLS в реальном времени. Удобно для быстрой проверки после изменений.
Инструмент Web Vitals на reChecker — проверка CLS без установки инструментов.
CLS тесно связан с LCP: резервирование размеров для изображений помогает обеим метрикам. Подробнее в руководстве по оптимизации LCP. Полный обзор всех Core Web Vitals — в руководстве Core Web Vitals 2026. Проверить текущие показатели можно в инструменте Web Vitals на reChecker.