БесплатноБесплатный прототип ключевой страницы и черновик ТЗ при старте проекта

Анимации без потери производительности: GPU и will-change

Плавные анимации без потери производительности: GPU-композитинг, transform, opacity и will-change

Красивая анимация — это ощущение качества интерфейса. Но та же анимация, сделанная неправильно, превращается в рывки, просадку FPS и «залипающую» прокрутку, особенно на бюджетных телефонах. Разница между плавным и дёрганым эффектом почти всегда не в дизайне, а в том, какие CSS-свойства анимируются и как браузер их обрабатывает.

Эта статья — инженерный разбор того, как делать анимации без потери производительности: как устроен конвейер рендеринга, почему transform и opacity дешёвые, а left и width дорогие, что реально делает will-change и как всё это не ломает Core Web Vitals. Тема тесно связана со скоростью в целом — её мы разбираем в статье про инфраструктуру на BitrixVM, а системную оптимизацию закрывает аудит и оптимизация 1С.

Коротко

  • Анимируйте transform и opacity — они идут через композитинг на GPU, минуя дорогие layout и paint.
  • Избегайте анимации left, top, width, height — они вызывают пересчёт геометрии на каждом кадре.
  • will-change — подсказка браузеру, а не ускоритель; применяйте точечно и снимайте после анимации.
  • Держите бюджет ~16 мс на кадр (60 FPS), не блокируйте главный поток и уважайте prefers-reduced-motion.

Почему анимации тормозят

Плавность анимации определяется тем, успевает ли браузер отрисовать каждый кадр вовремя. При 60 кадрах в секунду на один кадр есть около 16 миллисекунд, и в этот бюджет должна уложиться вся работа: пересчёт стилей, геометрии, отрисовка и сборка слоёв. Если не укладывается — кадр пропускается, и глаз видит рывок (jank).

Главная причина тормозов — анимация «дорогих» свойств, которые на каждом кадре заставляют браузер заново считать положение элементов и перерисовывать пиксели. Визуально результат может выглядеть так же, как у «дешёвой» анимации, но нагрузка отличается в разы. Понимание того, какая работа стоит за каждым свойством, — ключ к плавным анимациям.

Конвейер рендеринга: layout, paint, composite

Чтобы показать кадр, браузер проходит несколько стадий. Упрощённо:

Суть оптимизации анимаций — заставить браузер на каждом кадре делать как можно меньше стадий. Идеал — когда анимация затрагивает только composite, пропуская layout и paint. Именно это даёт максимально плавный результат при минимальной нагрузке.

Персональные рекомендации на основе модели Поведениепросмотры, покупкиМодельэмбеддинги / MLПохожие товарырядом в вектореРекомендациив карточке и корзине
Схема: поведение покупателей превращается в векторы (эмбеддинги), похожие товары оказываются рядом в пространстве — и попадают в блоки рекомендаций.

Дешёвые и дорогие свойства для анимации

СвойствоКакие стадии запускаетСтоимость
transform (translate, scale, rotate)Только compositeДёшево
opacityТолько compositeДёшево
left, top, marginLayout + paint + compositeДорого
width, heightLayout + paint + compositeДорого
box-shadow, backgroundPaint + compositeСредне-дорого
colorPaint + compositeСредне

Практический вывод простой: перемещение делайте через transform: translate(), а не через left/top; масштабирование — через transform: scale(), а не через width/height; появление и исчезновение — через opacity. Тот же визуальный эффект, но в разы дешевле для браузера.

GPU и композитные слои

Почему transform и opacity такие дешёвые? Потому что анимируемый элемент выносится на отдельный композитный слой — независимый «холст», который браузер может двигать и накладывать силами GPU, не перерисовывая соседей. Перемещение такого слоя — это просто пересборка картинки из готовых кусков, без пересчёта геометрии и повторной отрисовки.

Слои создаются автоматически для transform/opacity-анимаций или по подсказке will-change. Но у слоёв есть цена — память: каждый слой занимает видеопамять. Поэтому нельзя выносить на отдельные слои всё подряд: сотни слоёв «съедят» память и на слабом устройстве сделают только хуже. Баланс — выносить на слои именно то, что анимируется, и не больше.

Правило слоёв: композитный слой ускоряет анимацию конкретного элемента, но стоит памяти. Плодить слои «на всякий случай» вредно — это не бесплатное ускорение, а компромисс, который нужно применять осознанно.

Как правильно применять will-change

will-change заранее сообщает браузеру, что элемент будет меняться, чтобы тот подготовил композитный слой и убрал микроподтормаживание в самом начале анимации. Это полезный инструмент, но его массово переоценивают и неправильно используют.

Правила применения:

  1. Точечно, а не глобально. Не вешайте will-change на «всё, что шевелится» — это перерасход памяти.
  2. К конкретным свойствам. Указывайте, что именно изменится: will-change: transform, а не абстрактное «всё».
  3. Незадолго до анимации. В идеале добавлять перед началом и снимать после — но без частого дёрганья, которое само по себе стоит ресурсов.
  4. Не как ускоритель. Это подсказка, а не «турбо-кнопка»; неправильное применение ухудшает производительность.

На практике для многих CSS-анимаций will-change вообще не нужен: браузер и так создаёт слой под transform/opacity. Добавляйте его только там, где действительно видите подтормаживание в начале анимации.

Бюджет кадра и 60 FPS

Плавность измеряется в кадрах в секунду. Стандарт — 60 FPS, то есть ~16 мс на кадр на всю работу браузера. На экранах 90 и 120 Гц бюджет ещё жёстче — около 11 и 8 мс. Выход за бюджет означает пропущенные кадры и видимые рывки.

Чтобы укладываться в бюджет, важно не только анимировать дешёвые свойства, но и не занимать главный поток другой работой во время анимации. Тяжёлый JavaScript, синхронные вычисления, реакции на скролл — всё это конкурирует за те же миллисекунды. Особенно это критично на длинных списках товаров в каталоге, где к прокрутке добавляются эффекты появления карточек.

Анимации на JavaScript без рывков

Иногда анимацию удобнее делать на JS — но именно здесь легче всего получить рывки. Ключевые правила:

Для сложных сцен часто надёжнее и дешевле обычные CSS-анимации и переходы — браузер оптимизирует их лучше, чем ручной JS. К ручному JS прибегают, когда нужна логика, которую CSS не выражает.

Влияние на Core Web Vitals

Анимации связаны с метриками качества страницы, и связь эта двоякая. Неправильные анимации портят метрики:

При этом правильно сделанные композитные анимации transform/opacity почти не нагружают главный поток и на метрики практически не влияют. Вывод: анимация не враг производительности сама по себе — вредит именно неправильная реализация. Как метрики устроены в целом и как их держать в зелёной зоне, тесно связано со стеком D7 и архитектурой — об этом в статье про D7 и ORM в Битрикс.

Доступность и prefers-reduced-motion

Не все хотят видеть движение. Часть пользователей включает системную настройку уменьшения движения — по медицинским причинам (вестибулярные нарушения) или просто по предпочтению. Уважать её обязательно через медиазапрос prefers-reduced-motion.

При его активации крупные перемещения, параллаксы, автопрокрутки и резкие эффекты отключают или сильно упрощают, оставляя максимум мягкие переходы прозрачности. Ключевое правило: интерфейс должен оставаться полностью функциональным без анимаций — они украшают, но не несут смысла, без которого нельзя пользоваться сайтом. Это одновременно и доступность, и хороший инженерный тон.

Анимации в шаблонах 1С-Битрикс

На 1С-Битрикс анимации живут в CSS и JS шаблонов компонентов и общего шаблона сайта. Сами по себе они не мешают работе компонентов — проблемы начинаются, когда эффекты навешивают неаккуратно на нагруженные части витрины:

Правильный подход — лёгкие композитные анимации, уважение к производительности каталога и проверка на реальных устройствах, а не только на мощной машине разработчика.

Как измерять производительность анимаций

Плавность нельзя оценивать «на глаз» на мощном ноутбуке — нужно измерять на условиях аудитории:

  1. Панель Performance в DevTools. Записывает кадры и показывает, какие стадии (layout, paint, composite) выполняются и где рывки.
  2. FPS-метр. Индикатор частоты кадров при прокрутке и взаимодействии.
  3. Троттлинг CPU. Эмуляция медленного процессора, чтобы увидеть анимации глазами владельца бюджетного телефона.
  4. Слои (Layers). Панель, показывающая композитные слои и их количество — чтобы не расплодить лишние.

Главный принцип тот же, что и с Core Web Vitals: тестируйте на слабом устройстве, а не там, где «и так всё летает».

Частые ошибки

Чек-лист внедрения

  1. Анимируются дешёвые свойства. Перемещение и масштаб — через transform, появление — через opacity.
  2. Дорогие свойства убраны. Нет анимаций left/top/width/height в критичных местах.
  3. will-change точечный. Применён к конкретным элементам и свойствам, снимается после анимации.
  4. Слои под контролем. Композитных слоёв ровно столько, сколько нужно.
  5. JS-анимации через rAF. Нет layout thrashing, нет setInterval.
  6. Метрики не страдают. Анимации не создают CLS и не роняют INP.
  7. Reduced motion уважается. При системной настройке анимации упрощаются или отключаются.
  8. Проверено на слабом устройстве. FPS стабилен при троттлинге CPU и на бюджетном телефоне.

Вывод

Плавная анимация — это не про «больше эффектов», а про понимание того, какую работу браузер делает на каждом кадре. Секрет прост: анимируйте transform и opacity, которые идут через композитинг на GPU, и избегайте дорогих свойств, вызывающих пересчёт геометрии. Тогда тот же визуальный эффект укладывается в бюджет кадра без рывков.

will-change — тонкий инструмент, а не ускоритель: применяйте его точечно и снимайте после анимации. Держите число композитных слоёв разумным, не блокируйте главный поток тяжёлым JS, уважайте prefers-reduced-motion и всегда проверяйте на слабом устройстве, а не на своей мощной машине. Тогда анимации на сайте 1С-Битрикс будут украшать интерфейс, а не портить производительность и Core Web Vitals. Системно навести порядок во фронтенде поможет аудит и оптимизация 1С.

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

Почему анимация transform плавнее, чем анимация left или top?

Потому что они обрабатываются на разных стадиях рендеринга. Анимация свойств вроде left, top, width заставляет браузер пересчитывать геометрию страницы (layout) и перерисовывать пиксели (paint) на каждом кадре — это дорого. Свойства transform и opacity анимируются на стадии композитинга, минуя layout и paint, и обычно выполняются на GPU. Поэтому transform: translate плавнее и дешевле, чем изменение left, при визуально том же результате.

Что делает свойство will-change?

will-change заранее сообщает браузеру, что элемент будет анимироваться, чтобы тот подготовился — например, вынес элемент на отдельный композитный слой. Это может убрать подтормаживание в начале анимации. Но это подсказка, а не «ускоритель»: применённый бездумно ко множеству элементов, will-change съедает память и способен ухудшить производительность. Его добавляют точечно, к конкретным элементам, и по возможности снимают после анимации.

Что такое композитный слой и зачем он нужен?

Композитный слой — это отдельный «холст», который браузер может двигать и накладывать независимо от остального содержимого, часто силами GPU. Когда анимируемый элемент вынесен на свой слой, его перемещение и прозрачность не требуют перерисовки соседей — только пересборку слоёв (композитинг). Это делает анимацию дешёвой. Слои создаются автоматически для transform/opacity-анимаций или подсказкой will-change, но их число нужно держать разумным.

Сколько кадров в секунду нужно для плавной анимации?

Ориентир — 60 кадров в секунду, то есть на каждый кадр у браузера есть примерно 16 миллисекунд на всю работу. Если укладываться не получается, кадры «пропадают» и анимация выглядит рывками (jank). На устройствах с экранами 90 и 120 Гц бюджет на кадр ещё меньше. Поэтому анимировать нужно дешёвые свойства и не грузить главный поток тяжёлым JavaScript во время анимации.

Влияют ли анимации на Core Web Vitals?

Да, косвенно и напрямую. Анимации, вызывающие сдвиг контента, ухудшают CLS; тяжёлый анимационный JavaScript блокирует главный поток и портит INP — отзывчивость на действия. При этом правильно сделанные композитные анимации transform/opacity почти не нагружают главный поток и на метрики не влияют. Поэтому анимация — не враг производительности сама по себе, вредит именно неправильная её реализация.

Как анимировать на JavaScript, не роняя производительность?

Ключевое правило — использовать requestAnimationFrame для синхронизации с кадрами браузера и не трогать в цикле анимации свойства, вызывающие layout. Чтение геометрии (offsetWidth и подобных) вперемешку с записью стилей вызывает принудительные пересчёты (layout thrashing) и рывки. Лучше анимировать через transform/opacity, а тяжёлые вычисления выносить из кадрового цикла. Для сложных сцен часто надёжнее CSS-анимации, чем ручной JS.

Нужно ли учитывать настройку «уменьшить движение»?

Да. Часть пользователей включает системную настройку уменьшения движения (по медицинским причинам или предпочтению), и её уважают через медиазапрос prefers-reduced-motion. При его активации анимации отключают или сильно упрощают — убирают параллаксы, крупные перемещения, автопрокрутки. Это и вопрос доступности, и хорошая практика: интерфейс должен оставаться полностью функциональным без анимаций.

Мешают ли анимации на сайте 1С-Битрикс работе компонентов?

Сами по себе нет — анимации живут в шаблонах компонентов и общем шаблоне сайта, в их CSS и JS. Проблемы возникают, когда анимации навешивают на элементы каталога или умного фильтра неаккуратно: тяжёлые эффекты на большом списке товаров дают просадку при прокрутке. Правильный подход — лёгкие композитные анимации, минимум эффектов на длинных списках и уважение к производительности каталога, который и так нагружен.

Поделиться:

Анимации на сайте дёргаются и роняют FPS?

Найдём тяжёлые эффекты, переведём их на композитные свойства и уложим интерфейс в бюджет кадра без потери визуального качества.

Автоматизация на 1С

Игорь Воскресенский

Команда B2Bsite. С 2014 года разрабатываем интернет-магазины и порталы на 1С-Битрикс: делаем плавные интерфейсы, которые держат 60 FPS и не портят Core Web Vitals даже на бюджетных устройствах.

← Все статьи блога