Kodokon kodokon.com

Переходы и анимации: @keyframes, transform, тайминг

Анимируй на композиторе через transform и opacity, выстраивай свои @keyframes и уважай предпочтения пользователей по движению.

10 мин · 3 вопросов

Открыть этот урок в Kodokon

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

CSS
.button {
  transform: translateY(0);
  transition:
    transform 0.2s cubic-bezier(0.2, 0.8, 0.2, 1),
    opacity 0.15s ease-out;
}

.button:hover {
  transform: translateY(-2px);
}

.button:active {
  transform: translateY(0) scale(0.97);
}
Переход, дружелюбный к композитору, со своей кривой

Когда перехода уже не хватает (промежуточные шаги, зацикливание, автоматический старт), переходи к @keyframes. Две настройки отделяют аккуратную анимацию от визуального бага: animation-fill-mode управляет состоянием до старта (backwards применяет первый ключевой кадр во время задержки) и после окончания (forwards замораживает последний); both объединяет оба варианта. Учти также, что функция тайминга применяется между каждой парой ключевых кадров, а не ко всей длительности: её можно переопределить внутри ключевого кадра.

CSS
@keyframes slide-in {
  from {
    transform: translateX(-100%);
    opacity: 0;
  }
  70% {
    transform: translateX(8px);
    opacity: 1;
  }
  to {
    transform: translateX(0);
  }
}

.toast {
  animation: slide-in 0.35s ease-out both;
}
Появление с небольшим перелётом

Два дополнительных инструмента, которые стоит знать. will-change: transform заранее выносит элемент на отдельный слой, избегая запоздалой растеризации; но каждый слой стоит памяти GPU, поэтому включай его прямо перед анимацией и убирай после, а не оставляй постоянным стилем на десятках элементов. steps(n) заменяет непрерывную интерполяцию дискретными скачками: незаменимо для спрайтов, курсора в стиле печатной машинки или часов.

CSS
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
Уважаем prefers-reduced-motion

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Почему для анимированного перемещения лучше transform: translateX(100px), чем left: 100px?
    • transform лучше поддерживается старыми браузерами
    • transform обрабатывается композитором без пересчёта layout на каждом кадре
    • left работает только на абсолютно позиционированных элементах, а transform - везде
    • transform принимает отрицательные значения, в отличие от left
  2. Что делает animation-fill-mode: both?
    • Анимация проигрывается вперёд, а затем в обратную сторону
    • Анимация применяется к элементу и к его потомкам
    • Стили первого ключевого кадра действуют во время задержки, а стили последнего сохраняются после окончания
  3. Как правильно применять will-change?
    • Применять глобально на *, чтобы ускорить всю страницу
    • Добавлять прямо перед тяжёлой анимацией и убирать после неё
    • Всегда сочетать с transform: translateZ(0)
    • Использовать вместо transition для микровзаимодействий