Урок по треку HTML и CSS 6 мин

CSS-анимации без тормозов

transition и animation, что анимировать дёшево, will-change и prefers-reduced-motion.

В CSS два способа что-то двигать: transition и animation. Первый плавно переводит свойство из старого значения в новое, когда значение поменялось. Второй проигрывает заранее описанные кадры @keyframes сам по себе.

transition: «было - стало»

.button {
  background: #2563eb;
  transform: translateY(0);
  transition: background 200ms ease, transform 200ms ease-out;
}
.button:hover {
  background: #1d4ed8;
  transform: translateY(-2px);
}

Переход срабатывает только при смене значения: наведение, класс из JS, смена медиазапроса. Части шортхенда: свойство, длительность, функция времени, задержка. Первое время в записи - длительность, второе - задержка.

Чего transition не умеет:

  • запуститься сам при загрузке страницы (нужна смена значения или @starting-style);
  • анимировать до height: auto: браузер не интерполирует ключевое слово auto. Рабочий приём - обернуть контент в grid и анимировать grid-template-rows от 0fr к 1fr;
  • плавно скрыть элемент через display: none в старом коде: элемент исчезает мгновенно. Для плавного скрытия анимируют opacity и visibility.

transitionend срабатывает отдельно на каждое анимируемое свойство. Если переходят два свойства, событий будет два.

animation и @keyframes

@keyframes pulse {
  from { transform: scale(1); }
  50%  { transform: scale(1.08); }
  to   { transform: scale(1); }
}
.badge {
  animation: pulse 1.2s ease-in-out infinite;
}

Полезные свойства:

  • animation-iteration-count: число повторов или infinite;
  • animation-direction: alternate: туда, потом обратно;
  • animation-fill-mode: forwards: после окончания элемент остаётся в состоянии последнего кадра. Без него стили откатываются к исходным;
  • animation-play-state: paused: поставить на паузу;
  • animation-delay бывает отрицательной: анимация стартует «с середины».

Функции времени: ease (по умолчанию), linear, ease-in, ease-out, cubic-bezier(...) и steps(n) для покадровой анимации, например спрайтов.

Что анимировать дёшево

Кадр браузера: стили, layout (геометрия), paint (пиксели), composite (склейка слоёв). Чем раньше в цепочке задевает свойство, тем дороже кадр.

  • transform и opacity обычно затрагивают только composite и могут крутиться на потоке композитора даже при занятом главном потоке.
  • width, height, top, left, margin меняют геометрию: каждый кадр layout и paint.
  • background-color, box-shadow, color вызывают перерисовку без layout.

Хочешь сдвинуть элемент - transform: translate(), а не left. Хочешь «вырасти» - scale(), а не width.

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

Доступность

Часть людей плохо переносит движение на экране. Уважай системную настройку:

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Мигание чаще трёх раз в секунду опасно для людей с фоточувствительной эпилепсией.

Анимации из JS

Если анимацию нужно запускать и останавливать из кода, есть два пути:

  • переключать классы и отдавать движение CSS;
  • Web Animations API: el.animate(keyframes, { duration: 300 }) возвращает объект Animation с pause(), reverse(), finished (промис).

Ручные покадровые расчёты делают через requestAnimationFrame, а не setInterval: rAF синхронизирован с отрисовкой и засыпает в фоновой вкладке.

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

  • Анимируют left/top вместо transform и получают дёрганье на слабых телефонах.
  • Пишут transition: all: анимируется всё, включая то, что не планировали, и это дороже.
  • Забывают animation-fill-mode: forwards и удивляются, что элемент «прыгает» обратно.
  • Ставят will-change глобально.

Что спросят на собесе

  • Чем transition отличается от animation?
  • Какие свойства анимировать дёшево и почему?
  • Зачем will-change и чем опасен?
  • Как анимировать раскрытие блока неизвестной высоты?
  • Как учесть пользователей, которым мешает движение?

Закрепите за 5 минут

После урока в тренажёре 3-5 проверочных вопросов, дальше модуль уходит в повторения.