Конфликты с CSS

Библиотека Motion One управляет анимациями через Web Animations API и напрямую изменяет вычисляемые стили элемента, чаще всего затрагивая свойства transform, opacity, filter. Наиболее частая зона конфликтов возникает при одновременном участии CSS и JavaScript-анимаций в управлении одним и тем же визуальным свойством.

Свойство transform представляет собой композиционное значение, формируемое из нескольких функций: translate, scale, rotate, skew. CSS и Motion One не объединяют эти трансформации автоматически на уровне отдельных подфункций. При параллельном управлении:

  • CSS задаёт одно итоговое значение transform
  • Motion One перезаписывает его целиком
  • предыдущее значение полностью теряется

В результате любое CSS-описание трансформации становится неактуальным после первого кадра анимации, если Motion One начинает управление свойством.

Особенно заметно это при сочетании классов:

.card {
  transform: translateY(20px);
}

и анимации:

animate(element, { transform: "scale(1.1)" })

Финальный результат не объединяет оба состояния, а заменяет одно другим.


Пересечение CSS transitions и Motion One

CSS-переходы (transition) продолжают вычисляться браузером независимо от JavaScript-анимаций, если они затрагивают разные источники обновления стилей. Однако при совпадении свойства возникает конфликт вычислительного приоритета.

CSS:

.box {
  transition: transform 300ms ease;
}

Motion One:

animate(box, { x: 200 })

Внутренне Motion One изменяет transform через Web Animations API, минуя механизм CSS transition. Это приводит к тому, что:

  • CSS transition не активируется
  • промежуточные состояния transition не рассчитываются
  • итоговое значение устанавливается напрямую анимацией

Если одновременно происходит изменение класса, триггерящего transition, и запуск Motion One-анимации, результат определяется последним источником записи стиля в каждом кадре.


Ключевые кадры CSS и перезапись кадрового потока

CSS-анимации через @keyframes создают собственный поток значений, который обновляется на уровне композиционного движка браузера. Motion One, используя Web Animations API, формирует отдельный анимационный слой.

@keyframes float {
  from { transform: translateY(0); }
  to { transform: translateY(-20px); }
}
.box {
  animation: float 2s infinite;
}

При запуске Motion One:

animate(box, { y: 100 }, { duration: 1 })

происходит конкуренция за одно и то же свойство transform. В зависимости от браузера и очередности регистрации анимаций:

  • либо CSS keyframes продолжают применяться, но итоговое значение переопределяется Motion One
  • либо CSS-анимация останавливается при изменении inline-стилей
  • либо происходит смешивание на уровне композиции, если поддерживается additive animation

В большинстве практических случаев Web Animations API получает более высокий приоритет, так как записывает inline-стиль или активный анимационный слой.


Inline-стили и приоритет записи

Motion One при анимации создаёт или обновляет inline-значения свойств. Inline-стиль имеет более высокий приоритет, чем стили из CSS-классов.

.box {
  transform: translateX(0);
}

После выполнения:

animate(box, { x: 300 })

в DOM фиксируется вычисленное значение:

<div class="box" style="transform: translateX(300px);"></div>

Любая попытка изменить transform через класс перестаёт иметь визуальный эффект до завершения или отмены анимации.

Особенность заключается в том, что Motion One не добавляет «слои трансформаций», а полностью пересобирает строку transform, агрегируя все активные эффекты.


Конфликт с !important

CSS-декларации с !important создают повышенный приоритет в каскаде стилей. Однако Web Animations API и inline-стили работают вне классического CSS-каскада.

.box {
  transform: rotate(45deg) !important;
}

При запуске анимации Motion One:

animate(box, { rotate: 180 })

визуальное поведение определяется не каскадом, а механизмом анимации:

  • значение !important не блокирует Web Animations API
  • анимационный слой перекрывает вычисленный стиль
  • итоговое значение обновляется на каждом кадре

Таким образом, !important не является защитой от JavaScript-анимации в контексте Motion One.


Композиция transform и потеря независимых эффектов

Transform-система браузера не хранит независимые подзначения в виде отдельных CSS-правил после вычисления. Она хранит итоговую матрицу преобразования.

Motion One применяет объединённое преобразование:

  • translate
  • scale
  • rotate

При одновременном наличии CSS-эффекта и Motion One-эффекта происходит перезапись матрицы:

  • CSS формирует одну матрицу
  • Motion One формирует другую
  • итоговая матрица заменяется полностью

Это приводит к потере частичных эффектов, если они не включены в анимацию явно.


will-change и изменение слоёв композиции

Свойство will-change влияет на подготовку браузером композиционного слоя. CSS может заранее выделить элемент в отдельный слой:

.box {
  will-change: transform;
}

Motion One также инициирует работу с композитными слоями при анимации transform и opacity.

Конфликты возникают не на уровне значений, а на уровне:

  • избыточного создания слоёв
  • увеличения памяти GPU
  • деградации производительности при большом количестве анимаций

Если CSS заранее создаёт слой, а Motion One инициирует собственную оптимизацию, браузер может поддерживать несколько параллельных слоёв без необходимости, что приводит к росту нагрузки на композиционный этап.


Логика отмены CSS-анимаций при JS-управлении

При первом изменении inline-стиля через Motion One браузеры часто деактивируют CSS-анимации и transitions, затрагивающие те же свойства.

Причина заключается в модели вычисления:

  • CSS-анимация управляется декларативно
  • Web Animations API управляется императивно
  • при конфликте источников побеждает активный анимационный контроллер

В результате CSS-анимация может:

  • остановиться на текущем кадре
  • сброситься в начальное состояние
  • быть заменённой новым анимационным эффектом

Смешивание нескольких анимационных источников

При одновременном применении:

  • CSS keyframes
  • CSS transition
  • Motion One animation

браузер создаёт несколько уровней анимационного стека. Итоговое значение формируется по правилам композиции:

  • Web Animations API имеет приоритет над CSS Animations
  • CSS Animations выше CSS Transitions
  • inline-стиль фиксирует финальное значение

Однако поведение может различаться в зависимости от движка (Blink, Gecko, WebKit), особенно при сложных цепочках изменений DOM.


Прерывание анимаций при изменении классов

Изменение класса может приводить к пересозданию вычисленного стиля элемента. В момент активной анимации Motion One:

  • изменение класса не влияет на активное значение transform
  • но может изменить базовое состояние, используемое после завершения анимации

Если класс удаляет свойство transform, оно не восстановится автоматически после окончания Motion One-анимации, так как итоговое значение уже записано inline.


Влияние animation-fill-mode на итоговое состояние

CSS свойство animation-fill-mode определяет сохранение состояния ключевых кадров. Motion One аналогично использует параметры fill в Web Animations API.

При конфликте:

  • CSS может сохранять конечное состояние анимации
  • Motion One может переопределить итоговое значение inline-стилем

Это приводит к различию между:

  • визуальным состоянием во время анимации
  • состоянием после завершения

Если Motion One завершает анимацию с установкой финального значения, CSS-fill перестаёт иметь эффект.


Смешение координатных систем и transform-origin

CSS и Motion One могут по-разному интерпретировать transform-origin. При отсутствии явного задания:

  • CSS использует 50% 50%
  • Motion One опирается на вычисленный origin элемента

При конфликте:

  • вращение и масштабирование могут происходить вокруг разных точек
  • визуальное смещение становится несогласованным с CSS-разметкой

Особенно заметно при анимации scale и rotate одновременно с CSS позиционированием.


Режим уменьшенной анимации и блокировка Motion One

Media query:

@media (prefers-reduced-motion: reduce)

может отключать CSS-анимации, но не автоматически блокирует Motion One. При этом Motion One может:

  • продолжать выполнять анимации
  • либо требовать ручной фильтрации конфигурации

Возникает расхождение между декларативными CSS-ограничениями и программной логикой анимаций.


Конкуренция за кадры рендеринга

Motion One использует requestAnimationFrame и Web Animations API, что синхронизирует обновление с кадрами браузера. CSS-анимации также синхронизированы с compositor thread.

При высокой нагрузке:

  • CSS может отставать от JS-анимаций
  • JS может перезаписывать значения между кадрами CSS
  • возникает эффект «дребезга» состояний transform

Это особенно заметно при одновременном изменении layout-свойств и transform-анимаций.


Потеря предсказуемости при смешанном управлении стилями

Основной источник конфликтов заключается в различии моделей:

  • CSS управляет стилями декларативно
  • Motion One управляет вычисленным состоянием императивно

При наложении этих моделей:

  • каскад теряет детерминированность
  • итоговое значение определяется последним активным источником
  • промежуточные состояния становятся непредсказуемыми при множественных триггерах

В результате поведение определяется не CSS-структурой, а очередностью обновления анимационных слоёв в браузере