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

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

Мы же рассмотрим сложные анимации, в которых может быть указано не только состояние элемента в начале и конце, но и более тонкие настройки их протекания. Такие вещи в CSS осуществляются с помощью ключевого слова @keyframes и свойств animation-*.

Ключевое слово @keyframes

С помощью ключевого слова @keyframes мы сообщаем, что хотим изменить состояние элемента путем задавания ему ключевых кадров (этапов преобразования) и меняющихся свойств на каждом из них. Пример простого @keyframes:

@keyframes move {
  0% {
    transform: translate(0,0);
  }
  50% {
    transform: translate(50px,0);
  }
  100% {
    transform: translate(100px,50px);
  }
}

Этот @keyframes говорит нам о том, что мы хотим переместить наш элемент на 100px по оси X и на 50px по оси Y, причем сделать это в 2 этапа: первую половину пути элемент будет перемещаться только на 50px по оси X, а вторую половину - уже в конечную точку.

Согласно примеру, можем обозначить, что синтаксис этого правила состоит из трех частей:

  • само правило @keyframes с именем (move в нашем примере) анимации,
  • тело анимационного преобразования, состоящее из фигурных скобок,
  • набор кадров (проценты от всего цикла анимации) со свойствами, которые должны примениться к элементу на каждом из этапов.

Имя анимации чувствительно к регистру, поэтому move и Move будут разными именами. Кадры в анимации должны содержать процент от 0 до 100, причем порядок не имеет значения - браузер выполнит анимацию согласно возрастанию процентов. Если какие-то кадры имеют одинаковые стили, то их можно записать через запятую 10%, 80% {...}, а если в ваших стилях будет повторяющийся процент кадра, то отработает последний. Для простой анимации с двумя точками состояний (0 и 100) можно просто использовать слова from и to:

@keyframes increase {
  from {
    transform: scale(1);
  }
  to {
    transform: scale(1.8);
  }
}

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

Теперь, когда у нас есть именованное правило @keyframes, возникает вопрос - как собственно использовать эти преобразования на элементе и какие дополнительные конфигурации можно к ним применить.

Для этого существует набор определенных свойств, которые назначаются селектору и начинаются строкой animation-.

Свойство animation-name

Значением этого свойства будет являться имя применяемого к элементу @keyframes. Для примера выше стили элемента будут следующими:

.circle {
  animation-name: move;
}

Если в качестве значения animation-name указать несуществующее имя (т.е. @keyframes с таким именем не существует), то ничего не произойдет. Но зато один и тот же @keyframes может быть использован для разных селекторов.

Следует также учесть, что имя анимации должно начинаться с буквы или дефиса, может содержать цифры и символы и не может быть одним из зарезервированных слов (unset, initial, inherit). Если значение animation-name будет none, анимация будет деактивирована.

Свойство animation-duration

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

.circle {
  animation-duration: 3s;  /* 3 секунды */
}
.box {
  animation-duration: 2000ms;  /* 2 секунды */
}

Значение свойства не может быть отрицательным, может быть дробным и обязательно должно содержать единицу измерения.

Свойство animation-timing-function

Данное свойство определяет тип выполнения анимации. Вы возможно с подобным сталкивались, когда задавали значения для свойства transition.

Список возможных значений для animation-timing-function:

  • ease (по-умолчанию) - анимация начинается медленно, затем ускоряется и к концу движения опять замедляется;
  • ease-in - анимация начинается медленно, а к концу ускоряется;
  • ease-out - анимация начинается быстро, а к концу замедляется;
  • ease-in-out - анимация начинается медленно и к концу замедляется;
  • linear - скорость анимации постоянно одинаковая;
  • step-start - анимации нет, свойства сразу же принимают значение последнего кадра;
  • step-end - анимации нет, а свойства принимают значение последнего кадра через заданное время анимации;
  • cubic-bezier() - анимация задана кривой Безье, состоящей из набора точек;
  • steps() - анимация задана ступенчатой функцией с заданным числом шагов.
.circle {
  animation-timing-function: ease-in-out;
}

Свойство animation-iteration-count

Предоставленный вверху пример отображал ситуацию одноразовой анимации элемента. Свойство animation-iteration-count позволяет задать количество раз выполнения анимации.

.circle {
  animation-iteration-count: 3;
}

Стоит обратить внимание, что значение может быть дробным - в этом случае анимация недоотработает. Также можно выставить свойству значение infinite, позволяющее воспроизводить анимацию бесконечно. Дефолтное значение для animation-iteration-count - 1.

Свойство animation-direction

Это свойство хорошо работает в связке со свойством animation-iteration-count. Оно позволяет задать направление воспроизведения анимации.

Список возможных значений для animation-direction:

  • normal (по-умолчанию) - анимация воспроизводится от 0% к 100% кадров;
  • reverse - анимация воспроизводится в обратном направлении - от 100% к 0%;
  • alternate - первый цикл анимации воспроизводится в нормальном направлении, следующий - в обратном и так чередуются;
  • alternate-reverse - первый цикл анимации в обратном направлении, затем - прямой и так чередуются.
.circle {
  animation-direction: alternate;
}

Свойство animation-play-state

Свойство, позволяющее приостановить анимацию, принимает два значения: running и paused. По-умолчанию, любая анимация будет находиться в состоянии running. Однако, используя состояние наведения или клика, можно поменять значение animation-play-state на paused и анимация остановится, в каком бы состоянии она не находилась.

.circle:hover {
  animation-play-state: paused;
}

Пример ниже демонстрирует работоспособность вышеперечисленных свойств. Наведение на шар остановит анимацию.

Свойство animation-delay

По-умолчанию, любая анимация отрабатывает в тот же момент, когда и вызывается. Однако, существует возможность выполнять ее с задержкой. За это как раз и отвечает свойство animation-delay.

.circle {
  animation-delay: 2s;
}

Как и для свойства animation-duration, размерность должна быть указана в секундах (s) или миллисекундах (ms). Однако есть возможность выставить отрицательное значение - в этом случае анимация начнется в середине цикла.

Важно также отметить, что задержка анимации будет выполнена только для первого цикла. Дальше она будет протекать в нормальном режиме.

Свойство animation-fill-mode

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

Список возможных значений для animation-fill-mode:

  • none (по-умолчанию) - к элементу не применяются стили ни до, ни после анимации;
  • forwards - к элементу применяются стили последнего ключевого кадра анимации после окончания анимации;
  • backwards - к элементу применяются стили первого ключевого кадра анимации перед началом анимации;
  • both - объединение свойств forwards и backwards.
.circle {
  animation-fill-mode: both;
}

Свойство animation

Это свойство является сокращенным вариантом всех вышеперечисленных свойств. Таким образом, выражение:

.circle {
  animation-name: move;
  animation-duration: 3s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: 3;
  animation-direction: alternate;
  animation-delay: 2s;
  animation-fill-mode: both;
}

может быть заменено одной строкой:

.circle {
  animation: move 3s ease-in-out 3 alternate 2s both;
}

В сокращенной записи анимации правила можно писать в любом порядке. Однако стоит обратить внимание, что первое встретившееся время будет считано как animation-duration, а второе - как animation-delay. Неуказанные значения свойств примут дефолтное поведение.

Несколько анимаций для одного элемента

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

.circle {
  animation: move 3s ease-in-out infinite alternate, scale 5s ease 3s;
}

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

.circle {
  animation-name: move, scale;
  animation-duration: 3s, 5s;
  animation-timing-function: ease-in-out, ease;
  animation-iteration-count: infinite, 1;
  animation-direction: alternate, normal;
  animation-delay: 0s, 2s;
}

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