CSS: анимация

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

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

  • @keyframes
  • animation
  • animation-name
  • animation-duration
  • animation-delay
  • animation-iteration
  • animation-direction
  • animation-timing-function
  • animation-fill-mode

На самом деле, можно обойтись первыми двумя. Остальные свойства являются уточнениями свойства animation.

Очень простой пример перетекания цвета, реализованный с помощью CSS3 анимации:

<div></div>

@keyframes example {
    from {background-color: red;} /* Начальный цвет */
    to {background-color: yellow;} /* Конечный цвет */
}
 
div {
    width: 100px;
    height: 100px;
    background-color: red;
    animation-name: example;
    animation-duration: 4s;
}

Теперь про каждое свойство по отдельности.

@keyframes

@keyframes - основное свойство. В нем мы описываем нашу анимацию. Принцип его работы следующий:

  1. Разбиваем нашу анимацию по основным(ключевым) кадрам
  2. Описываем каждый кадр по отдельности

Синтаксис:

@keyframes имя_анимации {
  0% {
    свойство: значение;
    ...
    свойство: значение;
  }
  x2% {
    свойство: значение;
    ...
    свойство: значение;
  }
  ...
  x3% {
    свойство: значение;
    ...
    свойство: значение;
  }
  100% {
    свойство: значение;
    ...
    свойство: значение;
  }
}

Теперь подробнее. У нас есть анимация которая выполняет какую-то итерацию(100%). Мы указываем как объект должен выглядеть на каждом ключевом кадре, а CSS сам вычисляет все промежуточные состояния объекта. Как правило, ключевые кадры разбивают равномерно (например, 0%, 33%, 66%, 100% или 0%, 25%, 50%, 75%, 100%). В приведенном выше примере использовались ключевые слова "from" и "to" (которые представляет 0% (Начало) и 100% (Конец)).

animation-name

Свойство animation-name необходимо нам для указания имени анимации которую мы хотим применить к тому или иному объекту HTML.
Допустим, у нас есть какой-нибудь блок div с id="animated-block" и таблица стилей для него. Тогда для применения к нему анимации его стили станут такими:

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation-name: имя_анимации;
}

animation-duration

Свойство animation-duration позволяет указать время выполнения(в секундах) одной итерации анимации.

Например,

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation-duration: 3s;
}

animation-delay

Свойство animation-delay позволяет установить задержку(в секундах) анимации, т.е. начало ее выполнения.

Например,

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation-delay: 3s;
}

animation-iteration

Свойство animation-iteration определяет количество повторов анимации. Можно указать просто число(например, 5) или infinite - бесконечная анимация.

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation-iteration: infinite;
}

animation-direction

Свойство animation-direction позволяет указать порядок выполнения анимации.
Значения:
normal - анимирует в прямом порядке
reverse - анимирует в обратном порядке
alternate - анимирует в прямом, а затем в обратном порядке
alternate-reverse - анимирует в обратном, а затем в прямом порядке

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation-direction: alternate-reverse;
}

animation-timing-function

Свойство animation-timing-function определяет кривую скорости анимации. Включены следующие возможные значения:
ease - медленно начинается, затем ускоряется, затем снова замедляется
ease-in - медленно начинается
ease-in-out - медленно начинается и заканчивается
linear - равномерно движется
cubic-bezier(n, n, n, n) - позволяет задать собственные параметры в кубической кривой Безье.

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation-timing-function: linear;
}

animation-fill-mode

свойство animation-fill-mode позволяет переопределить нам состояние элемента после завершения анимации.
Возможные значения:
none - свойства анимации не сохранятся
forwards - сохранятся свойства первого ключевого кадра
backwards - сохранятся свойства последнего ключевого кадра
both - сохранятся свойства и первого, и последнего ключевых кадров

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation-fill-mode: forwards;
}

краткая запись всех свойств в одном:

.animated-block {
  свойство: значение;
  свойство: значение;
  ...
  animation: имя_анимации длительность кривая_скорости задержка число_итераций порядок_выполнения_кадров сохранение_свойств_анимации;
}

Так же, важно отметить, что анимации CSS не дают нам возможность запустить их в связи с каким-то событием(кликом, переходом на другой слайд в "карусели", полная прогрузка страницы и тому подобное), но эта проблема довольно просто решается средствами JS и еще одного свойства - animation-play-state со значениями paused и running. Просто в скрипте который контролирует состояние объекта нужно добавить стиль animation-play-state:paused, после чего анимация будет прекращать работу или наоборот запустить анимацию добавив стиль animation-play-state:running.

Например, у нас есть div с id="anim". Тогда остановить его анимацию можно следующей строкой:
document.getElementById('anim').style.animationPlayState="paused"

Пример анимации:
CSS-файл - animation.css

/* убираем все отступы  */
*{
  padding: 0;
  margin: 0;
}
/* для центрирования анимированного блока воспользуемся свойствами флексбокс
родительского */
.wrapper{
  width:100%;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  background-image: linear-gradient(to top, #9933ff, #66ffff);
}
/* Большой круг */
.big{
  background-image: radial-gradient(circle, #ff5000, #ff0);
  position: relative;
  animation: big 3s linear 0s infinite alternate none;
}
/* маленькие круги */
.little{
  width:26px;
  height:26px;
  border-radius: 13px;
  background-image: radial-gradient(circle, #ff5000, #ffff00);
  position: absolute;
  animation:little 3s linear 0s infinite alternate-reverse none;
}
/* расположение маленьких кругов по краям блока большого круга */
.el1{
top: 0;
left: 0;
}
.el2{
  top: 0;
  right: 0;
}
.el3{
  bottom: 0;
  left: 0;
}
.el4{
  bottom: 0;
  right: 0;
}
/* вращаем маленькие круги по оси Y  */
@keyframes little {
  0%  {transform: rotateY(0deg);}
  25%  {transform: rotateY(90deg);}
  50%  {transform: rotateY(180deg);}
  75%  {transform: rotateY(270deg);}
  100% {transform: rotateY(360deg);}
}
@keyframes big {
  /* меняем размер большого круга и вращаем его(вместе с маленькими кругами) вокруг центра */
  0%  {width:150px;height:150px;border-radius:75px;transform:rotate(0deg);}
  25%  {width:200px;height:200px;border-radius:100px;transform:rotate(90deg);}
  50%  {width:150px;height:150px;border-radius:75px;transform:rotate(180deg);}
  75%  {width:300px;height:300px;border-radius:150px;transform:rotate(270deg);}
  100%  {width:150px;height:150px;border-radius:100px;transform:rotate(360deg);}
}

html-файл - animation.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="animation.css">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <div class="wrapper">
    <div class="big">
      <div class="little el1"></div>
      <div class="little el2"></div>
      <div class="little el3"></div>
      <div class="little el4"></div>
    </div>
  </div>
</body>
</html>

Направление: