ToolHub
View All Posts

Руководство по CSS-анимации: переходы, ключевые кадры и производительность

CSS-анимации вдыхают жизнь в интерфейсы, обеспечивая визуальную обратную связь, направляя внимание пользователя и создавая запоминающиеся впечатления. Хорошо выполненная анимация ощущается естественной и интуитивной; плохо выполненная — вызывает задержки, отвлекает и даже может вызвать физический дискомфорт. Это руководство охватывает всё: от основ переходов и ключевых кадров до продвинутой оптимизации производительности и доступности, давая вам знания для создания плавных, целенаправленных и инклюзивных анимаций.

CSS-переходы и анимации

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

CSS-переходы

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

.button {
  background: #3b82f6;
  transform: scale(1);
  transition: background 0.3s ease, transform 0.2s ease;
}

.button:hover {
  background: #2563eb;
  transform: scale(1.05);
}

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

CSS-анимации (ключевые кадры)

Анимации используют правило @keyframes для определения последовательности изменений стиля с произвольным количеством шагов. В отличие от переходов, анимации могут работать независимо от изменений состояния, бесконечно зацикливаться, воспроизводиться в обратном направлении и приостанавливаться. Они дают вам точный контроль над каждым кадром анимации.

@keyframes pulse {
  0% {
    transform: scale(1);
    opacity: 1;
  }
  50% {
    transform: scale(1.05);
    opacity: 0.8;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}

.pulse-element {
  animation: pulse 2s ease-in-out infinite;
}

Когда что использовать

СценарийИспользовать переходыИспользовать анимации
Эффекты наведенияДаНет
Состояния фокусаДаНет
Переключение видимостиДаВозможно
Многошаговые последовательностиНетДа
Циклические анимацииНетДа
Независимо от состоянияНетДа
Анимации появленияВозможноДа

Подробный разбор синтаксиса ключевых кадров

Правило @keyframes является ядром CSS-анимации. Полное понимание его синтаксиса раскрывает всю мощь многошаговых анимационных последовательностей.

Ключевые кадры на основе процентов

Ключевые кадры определяются с использованием процентных значений от 0% до 100%, представляющих прогресс на временной шкале анимации. Вы можете определить столько ключевых кадров, сколько необходимо, а браузер выполняет интерполяцию между ними:

@keyframes bounce {
  0%, 100% {
    transform: translateY(0);
  }
  25% {
    transform: translateY(-20px);
  }
  50% {
    transform: translateY(0);
  }
  75% {
    transform: translateY(-10px);
  }
}

Несколько ключевых кадров могут совместно использовать один блок стилей, разделяя процентные значения запятыми, как в примере выше с 0%, 100%. Это полезно для анимаций, возвращающихся в начальное состояние.

Сокращённое свойство animation

Сокращённое свойство animation объединяет восемь подсвойств в одно объявление. Порядок: name, duration, timing-function, delay, iteration-count, direction, fill-mode и play-state.

.element {
  animation: slideIn 0.5s ease-out 0.2s 1 forwards running;
}

/* Equivalent longhand */
.element {
  animation-name: slideIn;
  animation-duration: 0.5s;
  animation-timing-function: ease-out;
  animation-delay: 0.2s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-play-state: running;
}

Режимы заполнения анимации

Свойство animation-fill-mode управляет тем, какие стили применяются до и после выполнения анимации. Это одно из наиболее часто неправильно понимаемых свойств анимации:

Функции плавности

Функции плавности (также называемые функциями времени) определяют кривую ускорения анимации. Они определяют, начинается ли анимация медленно и затем ускоряется, начинается быстро и затем замедляется, или следует более сложному шаблону. Правильная функция плавности делает анимацию естественной; неправильная — механической или резкой.

Встроенные функции плавности

Кубические кривые Безье

Функция cubic-bezier() позволяет определить пользовательскую кривую плавности с точным контролем. Она принимает четыре параметра, представляющих контрольные точки кубической кривой Безье: cubic-bezier(x1, y1, x2, y2). Значения x представляют время (от 0 до 1), значения y — прогресс (могут выходить за пределы 0-1 для эффектов перехлёста).

.element {
  /* Smooth deceleration - great for entrances */
  transition: transform 0.3s cubic-bezier(0.0, 0.0, 0.2, 1.0);

  /* Smooth acceleration - great for exits */
  transition: transform 0.2s cubic-bezier(0.4, 0.0, 1, 1);

  /* Material Design standard easing */
  transition: transform 0.3s cubic-bezier(0.4, 0.0, 0.2, 1);
}

Ступенчатые функции

Функция steps() создаёт дискретные покадровые анимации вместо плавной интерполяции. Это полезно для анимации спрайтов или создания эффекта «печати»:

@keyframes typing {
  from { width: 0; }
  to { width: 100%; }
}

.typing-effect {
  animation: typing 3s steps(40, end);
  overflow: hidden;
  white-space: nowrap;
}

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

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

Конвейер рендеринга

При изменении CSS-свойства браузер проходит до трёх этапов для обновления отображения:

  1. Стилизация: определение того, какие CSS-правила применяются к каким элементам.
  2. Макет: вычисление размера и положения каждого элемента. Запускается изменениями width, height, margin, padding, top, left, font-size и других геометрических свойств.
  3. Отрисовка: заполнение пикселей для каждого элемента. Запускается изменениями color, background, box-shadow, border-radius и других визуальных свойств.
  4. Композиция: объединение отрисованных слоёв в правильном порядке. Только этот шаг выполняется на GPU. Запускается изменениями transform и opacity.

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

Свойства только композиции

СвойствоЗапускает макет?Запускает отрисовку?GPU-композиция?
transformНетНетДа
opacityНетНетДа
filterНетДаИногда
top / leftДаДаНет
width / heightДаДаНет
margin / paddingДаДаНет
background-colorНетДаНет
box-shadowНетДаНет

Использование will-change

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

/* Apply will-change just before the animation */
.element:hover {
  will-change: transform;
}

/* Remove it after the animation completes */
.element {
  transition: transform 0.3s ease;
}

Распространённые ошибки will-change включают применение к слишком большому количеству элементов (каждый слой композитора потребляет память GPU) и постоянное удержание (трата ресурсов). Хорошая практика — добавлять will-change через JavaScript перед началом анимации и удалять после её завершения.

Использование Transform вместо свойств макета

Наиболее эффективная оптимизация производительности — замена свойств, запускающих макет, на transform:

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

Распространённые шаблоны анимации

Некоторые шаблоны анимации повторяются в веб-интерфейсах снова и снова. Освоение этих шаблонов даёт вам набор инструментов для большинства распространённых потребностей в UI-анимации.

1. Появление (fade-in)

Самая простая и универсальная анимация появления. Элемент переходит от прозрачного к непрозрачному:

@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

.fade-in {
  animation: fadeIn 0.4s ease-out forwards;
}

2. Появление со сдвигом вверх

Более динамичный эффект появления, сочетающий вертикальное перемещение с изменением прозрачности. Это создаёт ощущение, что элемент прибывает снизу:

@keyframes slideUpFade {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.slide-up {
  animation: slideUpFade 0.5s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

3. Масштабирование при наведении

Тонкое увеличение масштаба при наведении обеспечивает удовлетворительную интерактивную обратную связь:

.card {
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
  transform: translateY(-4px) scale(1.02);
  box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
}

4. Анимация списка с задержкой

Когда список элементов появляется, установка staggered задержки анимации для каждого элемента создаёт каскадный эффект, направляющий взгляд:

.list-item {
  opacity: 0;
  transform: translateY(10px);
  animation: slideUpFade 0.3s ease-out forwards;
}

.list-item:nth-child(1) { animation-delay: 0.0s; }
.list-item:nth-child(2) { animation-delay: 0.05s; }
.list-item:nth-child(3) { animation-delay: 0.1s; }
.list-item:nth-child(4) { animation-delay: 0.15s; }
.list-item:nth-child(5) { animation-delay: 0.2s; }

Для динамических списков используйте JavaScript для установки animation-delay на основе индекса каждого элемента или используйте CSS-пользовательские свойства: style="animation-delay: calc(var(--i) * 0.05s)".

5. Спиннер загрузки

Плавное непрерывное вращение — классический индикатор загрузки:

@keyframes spin {
  to { transform: rotate(360deg); }
}

.spinner {
  width: 24px;
  height: 24px;
  border: 3px solid rgba(255, 255, 255, 0.2);
  border-top-color: #3b82f6;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

Доступность анимации: prefers-reduced-motion

Не все пользователи получают пользу от анимации. Для людей с вестибулярными расстройствами, чувствительностью к движению или определёнными когнитивными состояниями анимация может вызывать головокружение, тошноту или судороги. Медиа-запрос prefers-reduced-motion позволяет уважать системные настройки пользователя по уменьшению анимации.

Реализация уменьшенной анимации

Рекомендуемый подход — включать анимацию для пользователей, не установивших предпочтение уменьшения движения:

/* Default: no animation for users who prefer reduced motion */
.element {
  opacity: 1;
  transform: none;
}

/* Only animate for users who have no motion preference */
@media (prefers-reduced-motion: no-preference) {
  .element {
    animation: slideUpFade 0.5s ease-out forwards;
  }
}

В качестве альтернативы можно отключить определённые анимации для пользователей, предпочитающих уменьшенное движение:

.element {
  animation: slideUpFade 0.5s ease-out forwards;
}

@media (prefers-reduced-motion: reduce) {
  .element {
    animation: none;
    opacity: 1;
    transform: none;
  }

  /* Keep functional transitions but shorten duration */
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

Что сохранить и что убрать

Когда пользователь предпочитает уменьшенную анимацию, не все анимации следует удалять. Функциональные анимации, передающие смысл или состояние, следует сохранить, но упростить:

Библиотеки анимации

Хотя CSS-анимации обрабатывают большинство потребностей UI, библиотеки JavaScript-анимаций предоставляют продвинутые возможности, такие как анимация на основе физики, анимация, связанная с прокруткой, и оркестровка сложных последовательностей.

CSS-ориентированные библиотеки

Библиотеки JavaScript-анимации

Когда использовать JavaScript против CSS

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

Отладка анимации

Ошибки анимации могут быть трудноуловимыми и сложными для диагностики. Правильные инструменты и техники отладки делают процесс более эффективным.

Панель анимации Chrome DevTools

Chrome DevTools включает специализированную панель анимации с мощными возможностями отладки:

Анализ производительности

Используйте панель Performance в Chrome DevTools для выявления проблем с производительностью анимации:

Распространённые сценарии отладки

Работаете с CSS? Попробуйте наши бесплатные инструменты CSS для форматирования, минификации и оптимизации ваших таблиц стилей для production.

CSS-форматтерCSS-минификатор

Часто задаваемые вопросы

Следует ли использовать CSS-переходы или CSS-анимации?

CSS-переходы используются для простых изменений состояния из точки A в точку B, таких как эффекты наведения, состояния фокуса и переключение видимости. CSS-анимации (ключевые кадры) используются для сложных многошаговых последовательностей, циклических анимаций или анимаций, которые должны работать независимо от изменений состояния. Переходы проще; анимации предоставляют больше контроля.

Какие CSS-свойства безопасно анимировать для производительности?

Наиболее производительными свойствами для анимации являются transform и opacity, поскольку они могут полностью обрабатываться композитором GPU без запуска макета или отрисовки. Другие свойства, такие как width, height, margin и top, запускают пересчёт макета, что дорого. Всегда предпочитайте transform: translateX() вместо left и transform: scale() вместо изменений width/height.

Как обеспечить доступность для пользователей, чувствительных к анимации?

Используйте медиа-запрос prefers-reduced-motion для отключения или упрощения анимации для пользователей, включивших настройку «уменьшить движение» в операционной системе. Оборачивайте несущественные анимации в @media (prefers-reduced-motion: no-preference) и предоставляйте мгновенные изменения состояния в качестве запасного варианта для пользователей, предпочитающих уменьшенную анимацию.

Что такое will-change и когда его следует использовать?

will-change — это CSS-свойство, которое подсказывает браузеру, какие свойства изменятся в будущем, позволяя ему оптимизироваться заранее. Используйте экономно и только при наблюдении проблем с производительностью. Применяйте перед началом анимации и удаляйте после её завершения. Чрезмерное использование will-change тратит память GPU и может фактически ухудшить производительность.

Как отлаживать CSS-анимации?

Chrome DevTools предоставляет мощные инструменты отладки анимации. Откройте панель Animations (в меню More Tools), чтобы увидеть все активные анимации, перетаскивать временную шкалу, изменять продолжительность и задержки в реальном времени и замедлять анимацию до 1/4 скорости. Вы также можете использовать панель Performance для выявления проблем с производительностью анимации и дрожания макета.