Анимации и transitions, не влияющие на CLS

Cumulative Layout Shift (CLS) — метрика, измеряющая суммарное смещение визуальных элементов на странице во время её загрузки и интерактивного использования. Высокие значения CLS вызывают неприятные визуальные эффекты: текст перескакивает, изображения меняют положение, кнопки сдвигаются, что ухудшает взаимодействие пользователя с сайтом.

Основной причиной CLS являются элементы, которые динамически меняют свои размеры или положение без заранее заданного пространства. Классические примеры: изображения без атрибутов width и height, динамически загружаемые баннеры, шрифты с FOUT/FOIT, рекламные блоки.

Анимации и transitions: отличие от layout shift

Анимации и CSS-переходы не обязательно влияют на CLS, если они не изменяют размеры элементов, занимаемых в потоке документа. Существует важное различие:

  1. Анимации, влияющие на layout

    • Изменение свойств width, height, margin, padding, top, left, bottom, right у элементов в нормальном потоке вызывает перерасчёт layout и потенциальный CLS.
    • Пример: плавное увеличение блока div с помощью height: 0 → height: 200px вызовет сдвиг контента ниже.
  2. Анимации, не влияющие на layout

    • Использование свойств transform и opacity не приводит к перерасчёту layout.
    • Пример: сдвиг с помощью transform: translateY(20px) или анимация появления через opacity: 0 → 1.
    • Такие анимации GPU-ускоренные, работают быстро и не создают CLS.

Рекомендации по безопасным анимациям

  • Использовать 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 при анимациях

Любая анимация, которая изменяет реальные размеры элемента или его позицию в потоке, будет учитываться как потенциальный 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;
}
  • Меняет размеры контейнера → вызывает CLS.

Исправление:

.menu {
    transform: scaleY(0);
    transform-origin: top;
    transition: transform 0.4s ease;
}
.menu.open {
    transform: scaleY(1);
}
  • Использует transform вместо изменения height → CLS отсутствует.

Практические инструменты контроля CLS

  • 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. Это повышает стабильность визуального отображения страницы и улучшает пользовательский опыт, что критично для современных веб-приложений.