Cumulative Layout Shift (CLS) — метрика, измеряющая суммарное смещение визуальных элементов на странице во время её загрузки и интерактивного использования. Высокие значения CLS вызывают неприятные визуальные эффекты: текст перескакивает, изображения меняют положение, кнопки сдвигаются, что ухудшает взаимодействие пользователя с сайтом.
Основной причиной CLS являются элементы, которые динамически меняют
свои размеры или положение без заранее заданного пространства.
Классические примеры: изображения без атрибутов width и
height, динамически загружаемые баннеры, шрифты с
FOUT/FOIT, рекламные блоки.
Анимации и CSS-переходы не обязательно влияют на CLS, если они не изменяют размеры элементов, занимаемых в потоке документа. Существует важное различие:
Анимации, влияющие на layout
width, height,
margin, padding, top,
left, bottom, right у элементов в
нормальном потоке вызывает перерасчёт layout и потенциальный CLS.div с помощью
height: 0 → height: 200px вызовет сдвиг контента ниже.Анимации, не влияющие на layout
transform и opacity
не приводит к перерасчёту layout.transform: translateY(20px) или
анимация появления через opacity: 0 → 1.Использовать transform для перемещений
.slide-up {
transform: translateY(100%);
transition: transform 0.5s ease-in-out;
}
.slide-up.active {
transform: translateY(0);
}
Контент визуально перемещается, но размеры родительского блока остаются неизменными.
Opacity для плавного появления/исчезновения
.fade {
opacity: 0;
transition: opacity 0.3s ease-in;
}
.fade.visible {
opacity: 1;
}
Не затрагивает layout и не вызывает CLS.
Комбинированные подходы через will-change
.animate {
will-change: transform, opacity;
}
Подсказывает браузеру заранее подготовить оптимизации для GPU, минимизируя потенциальные перерисовки.
Любая анимация, которая изменяет реальные размеры элемента или его позицию в потоке, будет учитываться как потенциальный CLS. Поэтому:
transform (translate, scale,
rotate) безопасны.position: absolute или fixed
также не вызывают CLS, если родительский layout не меняется.height, margin,
padding), следует избегать или задавать контейнеру
фиксированные размеры.Ошибка:
.menu {
height: 0;
transition: height 0.4s ease;
}
.menu.open {
height: 200px;
}
Исправление:
.menu {
transform: scaleY(0);
transform-origin: top;
transition: transform 0.4s ease;
}
.menu.open {
transform: scaleY(1);
}
Web Vitals API
import {getCLS} from 'web-vitals';
getCLS(console.log);
Позволяет отслеживать реальные значения CLS на странице.
DevTools Performance и Layout Shift Regions В Chrome DevTools можно включить Layout Shift Regions, чтобы визуально видеть элементы, вызывающие смещения.
Фреймворки и библиотеки При использовании React,
Vue, или других SPA, анимации компонентов через opacity и
transform предотвращают CLS, в то время как изменение
размеров через state напрямую может вызвать
сдвиги.
Соблюдение принципов использования transform и opacity вместо изменения layout позволяет создавать плавные анимации и transitions без негативного влияния на метрику CLS. Это повышает стабильность визуального отображения страницы и улучшает пользовательский опыт, что критично для современных веб-приложений.