Menu

Анимация в CSS: @keyframes, свойства animation и примеры

CSS-анимации проводят элемент через шаги, которые вы описали в @keyframes, сами по себе и сколько угодно раз. Разберем синтаксис @keyframes, все восемь свойств animation, fill-mode и direction, индикаторы загрузки, паузу и уважение к уменьшению движения.

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

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

У анимации две части: @keyframes, который описывает шаги, и свойство animation, которое применяет их к элементу с длительностью. Эта карточка выезжает и проявляется при загрузке страницы:

Измените код (или поменяйте длительность на 2s), и превью перезагрузится, так что вы снова увидите появление карточки. Блок @media (prefers-reduced-motion: reduce) заменяет ключевые кадры простым проявлением только для читателей, в чьей системе включено уменьшение движения.

Синтаксис @keyframes

@keyframes pulse {
  0%   { transform: scale(1); }
  50%  { transform: scale(1.08); }
  100% { transform: scale(1); }
}
  • from то же самое, что 0%, а to то же, что 100%.
  • Добавляйте сколько нужно процентных шагов. Шаги с одинаковыми стилями можно записать в одну строку: 0%, 100% { ... }.
  • Свойство, которого нет в первом или последнем ключевом кадре, анимируется от собственного значения элемента или к нему.
  • Имя (pulse) передается в animation-name. Регистр в нем важен, и оно не может быть ключевым словом вроде none.

Свойства animation

СвойствоЧто задаетПо умолчанию
animation-nameкакой @keyframes запускатьnone
animation-durationдлительность одного цикла0s
animation-timing-functionкривая скорости между ключевыми кадрамиease
animation-delayожидание перед первым циклом (отрицательное значение начинает с середины)0s
animation-iteration-countчисло циклов или infinite1
animation-directionnormal, reverse, alternate, alternate-reversenormal
animation-fill-modeстили до и после: none, forwards, backwards, bothnone
animation-play-staterunning или pausedrunning

Сокращенная запись принимает их почти в любом порядке. Правило одно: первое значение времени это длительность, второе задержка:

.loader {
  animation: pulse 1.2s ease-in-out 0.2s infinite alternate both;
  /*         name  duration timing  delay count   direction fill */
}

direction и fill-mode вживую

Выберите направление, режим заполнения и число повторов, затем нажмите Play. Блок сдвигается на 200px к концу дорожки. Ниже показано, где он остановился после окончания анимации:

На что смотреть:

  • fill-mode: none (по умолчанию): после последнего кадра блок прыгает обратно на x = 0 и снова становится янтарным.
  • forwards: остается на последнем ключевом кадре. С normal это x = 200 и зеленый; с reverse он заканчивает на x = 0 и синим, потому что последним проигрался кадр from.
  • alternate с числом повторов 2 идет туда и обратно, поэтому даже с forwards заканчивает на x = 0.

Бесконечные циклы: индикатор загрузки

infinite повторяет анимацию бесконечно, а animation-delay у каждого дочернего элемента сдвигает их, чтобы они двигались по очереди. Делайте циклы спокойными: медленными, небольшими, без мигания.

role="status" с aria-label сообщает пользователям программ чтения с экрана, что что-то загружается, чего одни точки не говорят. Вращающийся круг разобран на странице про поворот rotate.

Пауза и управление анимациями

animation-play-state: paused замораживает анимацию там, где она есть, а running продолжает ее оттуда. Наведите курсор на полосу ниже, чтобы поставить ее на паузу:

В JavaScript element.getAnimations() возвращает запущенные CSS-анимации, у каждой есть pause(), play(), cancel() и currentTime, который можно читать и задавать. Событие animationend срабатывает, когда заканчивается не бесконечная анимация, а animationiteration в конце каждого цикла.

Уменьшение движения и никакого мигания

Два правила доступности действуют для каждой анимации:

  1. Уменьшение движения. Люди могут попросить систему уменьшить движение, потому что им от него становится плохо. Самый надежный прием: добавлять движение, только если о его уменьшении не просили:
@media (prefers-reduced-motion: no-preference) {
  .hero-title { animation: slide-in 0.8s ease-out both; }
}
  1. Никакого мигания. Содержимое, которое мигает чаще трех раз в секунду, может вызвать приступ. Полностью избегайте быстрого контрастного мерцания.

Плавные анимации без рывков

По возможности анимируйте transform и opacity. Браузер применяет их без повторной раскладки страницы, поэтому они остаются плавными даже на медленных телефонах. Анимация width, height, top, left или margin пересчитывает раскладку на каждом кадре. Чтобы переместить элемент, используйте translate() со страницы про transform.

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

  • Нет длительности. animation: fade; ничего не делает, потому что длительность по умолчанию 0s.
  • Имя не совпадает. animation-name должно точно совпадать с именем @keyframes, включая регистр.
  • Прыжок обратно в конце. Добавьте forwards (или both), чтобы сохранить последний ключевой кадр.
  • Мерцание перед анимацией с задержкой. Во время animation-delay элемент показывает свои обычные стили. backwards (или both) применяет первый ключевой кадр во время задержки.
  • Перезапуск анимации тем же значением. Повторное присвоение того же animation ничего не делает. Уберите его, вызовите перерасчет раскладки (el.offsetWidth) и задайте снова, как делает кнопка Play выше.
  • Анимация display. Он меняется мгновенно. Анимируйте opacity и transform.

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

Как сделать анимацию в CSS?

Опишите шаги через @keyframes name { from { ... } to { ... } }, а затем примените их к элементу свойством animation с длительностью: animation: name 1s ease-out;. Длительность обязательна, потому что по умолчанию она 0s.

Что делает animation-fill-mode: forwards?

Сохраняет стили последнего ключевого кадра после окончания анимации. Без него элемент прыгает обратно к своим обычным стилям. backwards применяет первый ключевой кадр во время задержки, а both делает и то и другое.

Как зациклить CSS-анимацию навсегда?

Задайте animation-iteration-count: infinite или добавьте infinite в сокращенную запись: animation: spin 1s linear infinite;. Добавьте alternate, чтобы в каждом цикле анимация шла вперед, а затем назад.

Чем CSS-анимация отличается от перехода?

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

Как поставить CSS-анимацию на паузу?

Задайте элементу animation-play-state: paused, например в :hover или через класс, который добавляет JavaScript. Если вернуть running, анимация продолжится с того места, где остановилась.

Как отключить анимации для пользователей, которые предпочитают меньше движения?

Оберните анимацию в @media (prefers-reduced-motion: no-preference) { ... } или уберите ее внутри @media (prefers-reduced-motion: reduce) { ... }. Запрос следует настройке уменьшения движения в операционной системе пользователя.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ