CSS свойство animation-timing-function
Определение и применение
Свойство animation-timing-function определяет, как меняется прогресс между ключевыми кадрами анимации
элемента: равномерно, с ускорением, замедлением или скачками. Длительность цикла при этом не меняется.
Основы и примеры — в
уроке об анимациях CSS. Несколько
настроек можно объединить сокращённым свойством
animation.
В редакторе кривой плавности можно подобрать контрольные точки и сравнить движение с равномерным.
Попробуйте значения animation-timing-function
Меняется распределение скорости внутри прохода; steps делает движение ступенчатым.
animation-timing-function: linear
HTML и CSS примера
<div class="stage">
<div class="demo-target">CSS</div>
</div>
* {
box-sizing: border-box;
}
.stage {
width: 100%;
max-width: 300px;
height: 210px;
display: grid;
place-items: center;
padding: 20px;
border: 2px dashed #607589;
background: #edf2f5;
color: #172c3d;
font: 16px/1.4 system-ui;
}
.demo-target {
width: 100px;
height: 80px;
display: grid;
place-items: center;
border: 3px solid #245a85;
background: #ffe4bd;
animation-name: travel;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: linear;
}
@keyframes travel {
from {
transform: translateX(-55px);
}
to {
transform: translateX(55px);
}
}
@keyframes turn {
from {
transform: rotate(-30deg);
}
to {
transform: rotate(30deg);
}
}
* {
box-sizing: border-box;
}
.stage {
width: 100%;
max-width: 300px;
height: 210px;
display: grid;
place-items: center;
padding: 20px;
border: 2px dashed #607589;
background: #edf2f5;
color: #172c3d;
font: 16px/1.4 system-ui;
}
.demo-target {
width: 100px;
height: 80px;
display: grid;
place-items: center;
border: 3px solid #245a85;
background: #ffe4bd;
animation-name: travel;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in;
}
@keyframes travel {
from {
transform: translateX(-55px);
}
to {
transform: translateX(55px);
}
}
@keyframes turn {
from {
transform: rotate(-30deg);
}
to {
transform: rotate(30deg);
}
}
* {
box-sizing: border-box;
}
.stage {
width: 100%;
max-width: 300px;
height: 210px;
display: grid;
place-items: center;
padding: 20px;
border: 2px dashed #607589;
background: #edf2f5;
color: #172c3d;
font: 16px/1.4 system-ui;
}
.demo-target {
width: 100px;
height: 80px;
display: grid;
place-items: center;
border: 3px solid #245a85;
background: #ffe4bd;
animation-name: travel;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-out;
}
@keyframes travel {
from {
transform: translateX(-55px);
}
to {
transform: translateX(55px);
}
}
@keyframes turn {
from {
transform: rotate(-30deg);
}
to {
transform: rotate(30deg);
}
}
* {
box-sizing: border-box;
}
.stage {
width: 100%;
max-width: 300px;
height: 210px;
display: grid;
place-items: center;
padding: 20px;
border: 2px dashed #607589;
background: #edf2f5;
color: #172c3d;
font: 16px/1.4 system-ui;
}
.demo-target {
width: 100px;
height: 80px;
display: grid;
place-items: center;
border: 3px solid #245a85;
background: #ffe4bd;
animation-name: travel;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: ease-in-out;
}
@keyframes travel {
from {
transform: translateX(-55px);
}
to {
transform: translateX(55px);
}
}
@keyframes turn {
from {
transform: rotate(-30deg);
}
to {
transform: rotate(30deg);
}
}
* {
box-sizing: border-box;
}
.stage {
width: 100%;
max-width: 300px;
height: 210px;
display: grid;
place-items: center;
padding: 20px;
border: 2px dashed #607589;
background: #edf2f5;
color: #172c3d;
font: 16px/1.4 system-ui;
}
.demo-target {
width: 100px;
height: 80px;
display: grid;
place-items: center;
border: 3px solid #245a85;
background: #ffe4bd;
animation-name: travel;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: steps(4, end);
}
@keyframes travel {
from {
transform: translateX(-55px);
}
to {
transform: translateX(55px);
}
}
@keyframes turn {
from {
transform: rotate(-30deg);
}
to {
transform: rotate(30deg);
}
}
Поддержка браузерами
Спецификация: CSS animations
Поддерживается во всех основных браузерах с 2016 года.
| Возможность | Компьютеры | Мобильные | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
animation-timing-function | 43 Версия 43 выпущена в 2015 г. Версия 3 выпущена в 2009 г. — Префикс -webkit- | 12 Версия 12 выпущена в 2015 г. Версия 12 выпущена в 2015 г. — Префикс -webkit- | 16 Версия 16 выпущена в 2012 г. Версия 49 выпущена в 2016 г. — Префикс -webkit- Версия 5 выпущена в 2011 г. — Префикс -moz- | 30 Версия 30 выпущена в 2015 г. Версия 15 выпущена в 2013 г. — Префикс -webkit- Версия 12.1 выпущена в 2012 г. — Удалено в 15 Версия 12 выпущена в 2012 г. — Удалено в 15; Префикс -o- | 9 Версия 9 выпущена в 2015 г. Версия 4 выпущена в 2009 г. — Префикс -webkit- | 43 Версия 43 выпущена в 2015 г. Версия 18 выпущена в 2012 г. — Префикс -webkit- | 16 Версия 16 выпущена в 2012 г. Версия 49 выпущена в 2016 г. — Префикс -webkit- Версия 5 выпущена в 2011 г. — Префикс -moz- | 30 Версия 30 выпущена в 2015 г. Версия 14 выпущена в 2013 г. — Префикс -webkit- Версия 12.1 выпущена в 2012 г. — Удалено в 14 Версия 12 выпущена в 2012 г. — Удалено в 14; Префикс -o- | 9 Версия 9 выпущена в 2015 г. Версия 3.2 выпущена в 2010 г. — Префикс -webkit- | 4.0 Версия 4.0 выпущена в 2016 г. Версия 1.0 выпущена в 2013 г. — Префикс -webkit- | 43 Версия 43 выпущена в 2015 г. Версия 4.4 выпущена в 2013 г. — Префикс -webkit- | 9 Версия 9 выпущена в 2015 г. Версия 3.2 выпущена в 2010 г. — Префикс -webkit- |
ease | 3 | 12 | 5 | 15 | 4 | 18 | 5 | 14 | 3.2 | 1.0 | 4.4 | 3.2 |
ease-in | 3 | 12 | 5 | 15 | 4 | 18 | 5 | 14 | 3.2 | 1.0 | 4.4 | 3.2 |
ease-in-out | 3 | 12 | 5 | 15 | 4 | 18 | 5 | 14 | 3.2 | 1.0 | 4.4 | 3.2 |
ease-out | 3 | 12 | 5 | 15 | 4 | 18 | 5 | 14 | 3.2 | 1.0 | 4.4 | 3.2 |
jump | 77 | 79 | 65 | 64 | 14 | 77 | 65 | 55 | 14 | 12.0 | 77 | 14 |
linear | 3 | 12 | 5 | 15 | 4 | 18 | 5 | 14 | 3.2 | 1.0 | 4.4 | 3.2 |
step-end | 3 | 12 | 5 | 15 | 4 | 18 | 5 | 14 | 3.2 | 1.0 | 4.4 | 3.2 |
step-start | 3 | 12 | 5 | 15 | 4 | 18 | 5 | 14 | 3.2 | 1.0 | 4.4 | 3.2 |
поддерживаетсяс ограниченияминет поддержкинет данных≤31 — не позднее версии 31
Функция linear() новее ключевого слова linear и имеет отдельную поддержку. Проверяйте её для
целевых браузеров; готовые кривые и steps() не требуют linear().
CSS синтаксис:
/* Готовые функции */
animation-timing-function: [ linear | ease | ease-in | ease-out | ease-in-out | step-start | step-end ]#;
/* Настраиваемые функции */
animation-timing-function: [ cubic-bezier(<number [0,1]>, <number>, <number [0,1]>, <number>)
| steps(<integer [1,∞]> [ , <step-position> ]?)
| linear( [ <number> && <percentage>{0,2} ]# ) ]#;
/* Глобальные значения */
animation-timing-function: initial | inherit | unset | revert | revert-layer;
<number> — число, [0,1] ограничивает его диапазон;
<integer [1,∞]> — положительное целое. <percentage> — позиция в процентах;
{0,2} означает до двух позиций. && объединяет части в любом порядке (позиции здесь
необязательны), ? — необязательная часть. <step-position>:
jump-start | jump-end | jump-none | jump-both | start | end. В одном списке можно смешивать готовые и
настраиваемые функции. Знак # означает одно или несколько значений через запятую. Знак
| разделяет варианты. Квадратные скобки группируют варианты.
JavaScript синтаксис:
element.style.animationTimingFunction = "ease-in-out";Начальное значение свойства
ease.
Значения свойства
| Значение | Описание |
|---|---|
ease |
Плавный старт, ускорение и замедление к концу: cubic-bezier(0.25, 0.1, 0.25, 1).
Начальное значение.
|
linear |
Равномерное изменение прогресса. |
ease-in |
Ускорение: cubic-bezier(0.42, 0, 1, 1). |
ease-out |
Замедление: cubic-bezier(0, 0, 0.58, 1). |
ease-in-out |
Ускорение и замедление: cubic-bezier(0.42, 0, 0.58, 1). |
cubic-bezier(x1, y1, x2, y2) |
Кривая по двум контрольным точкам. Только x1 и x2 ограничены диапазоном от
0 до 1; y1 и y2 могут выходить за него. Подобрать
контрольные точки, сравнить движение и скопировать готовое значение можно в
нашем редакторе кривой плавности.
|
steps(n, position) |
Ступенчатая функция. n — положительное целое; для jump-none требуется минимум
2. jump-start/start делает скачок в начале, jump-end/end
— в конце. jump-none не делает скачков на обоих краях, jump-both делает на обоих. По
умолчанию jump-end.
|
step-start |
Эквивалент steps(1, jump-start). |
step-end |
Эквивалент steps(1, jump-end). |
linear(...) |
Кусочно-линейная функция через минимум две точки, например linear(0, 0.3 50%, 1). Числа задают
выходной прогресс, проценты — входную позицию; пропущенные позиции распределяются автоматически.
|
initial |
Устанавливает начальное значение свойства. |
inherit |
Наследует вычисленное значение свойства у родительского элемента. |
unset |
Для ненаследуемого свойства animation-timing-function устанавливает его
начальное значение.
|
revert |
Отменяет заданное в коде значение свойства для этого элемента: применяются пользовательские или стандартные стили браузера. Если они не задают значение, свойство наследуется или получает начальное значение по обычным правилам. Не возвращает значение из предыдущей строки CSS. |
revert-layer |
Сбрасывает значение свойства для текущего слоя каскада @layer. Применяется значение из другого слоя
по правилам каскада; если подходящего значения нет, возможен откат к стилям пользователя или браузера.
|
Значения через запятую соответствуют именам в
animation-name
по порядку. Если значений меньше, список повторяется; лишние значения не используются.
Функция времени в ключевом кадре
Значение внутри @keyframes действует от этого кадра до следующего кадра соответствующего свойства. На
последнем кадре 100% оно не используется.
@keyframes travel {
0% { transform: translateX(0); }
25% { transform: translateX(40px); animation-timing-function: linear; }
100% { transform: translateX(160px); }
}Спецификация
Наследуется
Нет.
Анимируемое
Нет.
Примеры, попробуйте сами
Равномерное движение и ускорение
Обе дорожки проходят одинаковый путь за 3s. Сравните linear и ease-in-out; замените второе значение на ease-in или ease-out.
base.css
* {
box-sizing: border-box;
}
body {
margin: 16px;
font:
16px/1.4 system-ui,
sans-serif;
color: #172c3d;
}
.track {
position: relative;
height: 70px;
margin-top: 16px;
border: 1px dashed #607589;
background: #edf2f5;
}
.box {
position: absolute;
top: 12px;
left: 0;
width: 42px;
height: 42px;
display: grid;
place-items: center;
border-radius: 6px;
background: #245a85;
color: white;
}
.run:not(:checked) ~ .track .box {
animation-name: none;
}
index.html
<input class="run" type="checkbox" id="run" checked />
<label for="run">Запустить анимацию</label>
<div class="track"><span class="box">A</span></div>
<div class="track second"><span class="box">B</span></div>
style.css
.box {
animation-name: travel;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-direction: alternate;
animation-timing-function: linear;
}
.second .box {
animation-timing-function: ease-in-out;
}
/* Длина пути зависит от ширины дорожки: пример помещается на телефоне. */
@keyframes travel {
from {
left: 0;
background: #a64400;
}
to {
left: calc(100% - 42px);
background: #16703c;
}
}
Движение по шагам
Сравните плавное движение linear и четыре скачка steps(4, end). Измените число шагов или замените end на start.
base.css
* {
box-sizing: border-box;
}
body {
margin: 16px;
font:
16px/1.4 system-ui,
sans-serif;
color: #172c3d;
}
.track {
position: relative;
height: 70px;
margin-top: 16px;
border: 1px dashed #607589;
background: #edf2f5;
}
.box {
position: absolute;
top: 12px;
left: 0;
width: 42px;
height: 42px;
display: grid;
place-items: center;
border-radius: 6px;
background: #245a85;
color: white;
}
.run:not(:checked) ~ .track .box {
animation-name: none;
}
index.html
<input class="run" type="checkbox" id="run" checked />
<label for="run">Запустить анимацию</label>
<div class="track"><span class="box">A</span></div>
<div class="track second"><span class="box">B</span></div>
style.css
.box {
animation-name: travel;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.second .box {
animation-timing-function: steps(4, end);
}
/* Длина пути зависит от ширины дорожки: пример помещается на телефоне. */
@keyframes travel {
from {
left: 0;
background: #a64400;
}
to {
left: calc(100% - 42px);
background: #16703c;
}
}
Пользовательские функции времени
Все три блока проходят одинаковый путь за 4s. A движется равномерно, B ускоряется по cubic-bezier(), C использует linear() с паузой в середине. Измените координаты кривой B или позиции 25% и 75% у C. Функция linear() требует поддерживающего её браузера; иначе C использует резервное linear.
base.css
* {
box-sizing: border-box;
}
body {
margin: 16px;
font:
16px/1.4 system-ui,
sans-serif;
color: #172c3d;
}
.track {
position: relative;
height: 70px;
margin-top: 16px;
border: 1px dashed #607589;
background: #edf2f5;
}
.box {
position: absolute;
top: 12px;
left: 0;
width: 42px;
height: 42px;
display: grid;
place-items: center;
border-radius: 6px;
background: #245a85;
color: white;
}
.run:not(:checked) ~ .track .box {
animation-name: none;
}
index.html
<input class="run" type="checkbox" id="run" checked />
<label for="run">Запустить анимацию</label>
<div class="track"><span class="box">A</span></div>
<div class="track second"><span class="box">B</span></div>
<div class="track third"><span class="box">C</span></div>
style.css
.box {
animation-name: travel;
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.second .box {
animation-timing-function: cubic-bezier(0.42, 0, 1, 1);
}
.third .box {
/* Резервное linear задано общим правилом выше. */
animation-timing-function: linear(0, 0.5 25%, 0.5 75%, 1);
}
@keyframes travel {
from {
left: 0;
}
to {
left: calc(100% - 42px);
}
}
Функция времени внутри ключевого кадра
A движется равномерно на обоих участках. У B функция steps(2, end), записанная в кадре 50%, действует только на вторую половину цикла. Замените её на ease-in или перенесите в кадр from: сравните, какой участок изменился. Значение на кадре 100% не задаёт следующий участок.
base.css
* {
box-sizing: border-box;
}
body {
margin: 16px;
font:
16px/1.4 system-ui,
sans-serif;
color: #172c3d;
}
.track {
position: relative;
height: 70px;
margin-top: 16px;
border: 1px dashed #607589;
background: #edf2f5;
}
.box {
position: absolute;
top: 12px;
left: 0;
width: 42px;
height: 42px;
display: grid;
place-items: center;
border-radius: 6px;
background: #245a85;
color: white;
}
.run:not(:checked) ~ .track .box {
animation-name: none;
}
index.html
<input class="run" type="checkbox" id="run" checked />
<label for="run">Запустить анимацию</label>
<div class="track"><span class="box">A</span></div>
<div class="track second"><span class="box">B</span></div>
style.css
.box {
animation-duration: 4s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-name: steady;
}
.second .box {
animation-name: segmented;
}
@keyframes steady {
from {
left: 0;
}
50% {
left: calc(50% - 21px);
}
to {
left: calc(100% - 42px);
}
}
@keyframes segmented {
from {
left: 0;
}
50% {
left: calc(50% - 21px);
/* Эта функция действует от 50% до 100%. */
animation-timing-function: steps(2, end);
}
to {
left: calc(100% - 42px);
}
}