# CSS-анимации
Все современные браузеры, кроме IE9- поддерживают CSS transitions и CSS animations, которые позволяют реализовать анимацию средствами CSS, без привлечения JavaScript.
Однако, как мы увидим далее, для более тонкого контроля анимации JavaScript вовсе не будет лишним.
[cut]
## CSS transitions [#css-transition]
Идея проста. Мы указываем, что некоторое свойство будет анимироваться при помощи специальных CSS-правил. Далее, при изменении этого свойства, браузер сам обработает анимацию.
Например, CSS, представленный ниже, 3 секунды анимирует свойство `background-color`.
```css
.animated {
transition-property: background-color;
transition-duration: 3s;
}
```
Теперь любое изменение фонового цвета будет анимироваться в течение 3х секунд.
При клике на эту кнопку происходит анимация её фона:
```html run autorun height=60
```
Есть всего 5 свойств, задающих анимацию:
- `transition-property`
- `transition-duration`
- `transition-timing-function`
- `transition-delay`
Далее мы изучим их все, пока лишь заметим, что общее свойство `transition` может перечислять их все, в порядке: `property duration timing-function delay`, а также задавать анимацию нескольких свойств сразу.
Например, при клике на эту кнопку анимируются одновременно цвет и размер шрифта:
```html run height=80 autorun no-beautify
```
Далее мы рассмотрим свойства анимации по отдельности.
## transition-property
Список свойств, которые будут анимироваться, например: `left`, `margin-left`, `height`, `color`.
Анимировать можно не все свойства, но [многие](http://www.w3.org/TR/css3-transitions/#animatable-properties-). Значение `all` означает "анимировать все свойства".
## transition-duration
Продолжительность анимации, задаётся в формате [CSS time](http://www.w3.org/TR/css3-values/#time), то есть в секундах `s` или `ms`.
## transition-delay
Задержка до анимации. Например, если `transition-delay: 1s`, то анимация начнётся через 1 секунду после смены свойства.
Возможны отрицательные значения, при этом анимация начнётся с середины.
Например, вот анимация цифр от `0` до `9`:
[codetabs src="digits"]
Она осуществляется сменой `margin-left` у элемента с цифрами, примерно так:
```css
#stripe.animate {
margin-left: -174px;
transition-property: margin-left;
transition-duration: 9s;
}
```
В примере выше JavaScript просто добавляет элементу класс -- и анимация стартует:
```js
digit.classList.add('animate');
```
Можно стартовать её "с середины", с нужной цифры, например соответствующей текущей секунде, при помощи отрицательного `transition-delay`.
В примере ниже при клике на цифру она начнёт двигаться с текущей секунды:
[codetabs src="digits-negative-delay"]
В JavaScript это делается дополнительной строкой:
```js
stripe.onclick = function() {
let sec = new Date().getSeconds() % 10;
*!*
// например, значение -3s начнёт анимацию с 3-й секунды
stripe.style.transitionDelay = '-' + sec + 's';
*/!*
stripe.classList.add('animate');
};
```
## transition-timing-function
Временнáя функция, которая задаёт, как процесс анимации будет распределён во времени, например начнётся ли анимация медленно, чтобы потом ускориться или наоборот.
Самое сложное, но при небольшом изучении -- вполне очевидное свойство.
У него есть два основных вида значения: кривая Безье и по шагам. Начнём с первого.
### Кривая Безье
В качестве временной функции можно выбрать любую [кривую Безье](/bezier) с 4 опорными точками, удовлетворяющую условиям:
1. Начальная точка `(0,0)`.
2. Конечная точка `(1,1)`.
3. Для промежуточных точек значения `x` должны быть в интервале `0..1`, `y` -- любыми.
Синтаксис для задания кривой Безье в CSS: `cubic-bezier(x2, y2, x3, y3)`. В нём указываются координаты только двух точек: второй и третьей, так как первая и последняя фиксированы.
Она указывает, как быстро развивается процесс анимации во времени.
- По оси `x` идёт время: `0` -- начальный момент, `1` -- конец времени `transition-duration`.
- По оси `y` -- завершённость процесса: `0` -- начальное значение анимируемого свойства, `1` -- конечное.
Самый простой вариант -- это когда процесс развивается равномерно, "линейно" по времени. Это можно задать кривой Безье `cubic-bezier(0, 0, 1, 1)`.
График этой "кривой" таков:

...Как видно, это просто прямая. По мере того, как проходит время `x`, завершённость анимации `y` равномерно приближается от `0` к `1`.
Поезд в примере ниже с постоянной скоростью "едет" слева направо, используя такую временную функцию:
[codetabs src="train-linear"]
CSS для анимации:
```css
.train {
left: 0;
transition: left 5s cubic-bezier(0, 0, 1, 1);
/* JavaScript ставит значение left: 450px */
}
```
Как нам показать, что поезд тормозит?
Для этого используем кривую Безье: `cubic-bezier(0.0, 0.5, 0.5 ,1.0)`.
График этой кривой:

Как видно, процесс вначале развивается быстро -- кривая резко идёт вверх, а затем всё медленнее, медленнее.
Вы можете увидеть эту временную функцию в действии, кликнув на поезд:
[codetabs src="train"]
CSS для анимации:
```css
.train {
left: 0;
transition: left 5s cubic-bezier(0, .5, .5, 1);
/* JavaScript ставит значение left: 450px */
}
```
Существует несколько стандартных обозначений кривых: `linear`, `ease`, `ease-in`, `ease-out` и `ease-in-out`.
Значение `linear` -- это прямая, мы её уже видели.
Остальные кривые являются короткой записью следующих `cubic-bezier`:
| ease
* | ease-in
| ease-out
| ease-in-out
|
|-------------------------------|----------------------|-----------------------|--------------------------|
| (0.25, 0.1, 0.25, 1.0)
| (0.42, 0, 1.0, 1.0)
| (0, 0, 0.58, 1.0)
| (0.42, 0, 0.58, 1.0)
|
|  |  |  |  |
`*` -- По умолчанию, если никакой временной функции не указано, используется `ease`.
**Кривая Безье может заставить анимацию "выпрыгивать" за пределы диапазона.**
Допустимо указывать для кривой Безье как отрицательные `y`, так и сколь угодно большие. При этом кривая Безье будет также по `y` выскакивать за пределы диапазона `0..1`, представляющего собой начало-конец значения.
В примере ниже CSS-код анимации таков:
```css
.train {
left: 100px;
transition: left 5s cubic-bezier(.5, -1, .5, 2);
/* JavaScript поменяет left на 400px */
}
```
Свойство `left` должно меняться от `100px` до `400px`.
Однако, если кликнуть на поезд, то мы увидим, что:
- Он едет сначала назад, то есть `left` становится меньше `100px`.
- Затем вперёд, причём выезжает за назначенные `400px`.
- А затем опять назад -- до `400px`.
[codetabs src="train-over"]
Почему так происходит -- отлично видно, если взглянуть на кривую Безье с указанными опорными точками:

Мы вынесли координату `y` для второй опорной точки на 1 ниже нуля, а для третьей опорной точки -- на 1 выше единицы, поэтому и кривая вышла за границы "обычного" квадрата. Её значения по `y` вышли из стандартного диапазона `0..1`.
Как мы помним, значению `y = 0` соответствует "нулевое" положение анимации, а `y = 1` -- конечное. Получается, что значения `y<0` двинули поезд назад, меньше исходного `left`, а значения `y>1` -- больше итогового `left`.
Это, конечно, "мягкий" вариант. Если поставить значения `y` порядка `-99`, `99`, то поезд будет куда более сильно выпрыгивать за диапазон.
Итак, кривая Безье позволяет задавать "плавное"" течение анимации. Подобрать кривую Безье вручную можно на сайте