animation-duration задаёт, сколько длится ОДИН цикл анимации, а animation-iteration-count - сколько раз этот цикл повторится. По умолчанию длительность равна 0 секунд (без явного значения анимация не видна), а количество повторов равно 1 - анимация проигрывается всего один раз, а не бесконечно, как иногда ожидают. Дробные значения повтора (например 2.5) останавливают анимацию ровно на середине цикла.
В этом уроке
Попробуй прямо сейчас: полоска заполняется за 2 секунды (animation-duration: 2s) и, дойдя до конца, заново стартует с нуля (animation-iteration-count: infinite) - как и положено индикатору загрузки. Поменяй animation-iteration-count на 1 - полоска заполнится всего один раз и на этом остановится: после окончания она вернётся к пустому виду, потому что мы ещё не указали браузеру "сохрани финальный вид" (это тема урока 20). Попробуй и animation-duration - например 5s вместо 2s - заполнение станет заметно медленнее.
animation-duration: сколько длится один цикл
animation-duration задаёт время ОДНОГО прохода анимации - от 0% до 100% в @keyframes. Без явного значения длительность равна 0 секунд, и анимация технически запускается и сразу заканчивается, ничего не показывая. Как и у transition-duration из урока 03, единица измерения ОБЯЗАТЕЛЬНА: собственная проверка подтвердила, что animation-duration: 2; (без "s") делает всю запись невалидной, и вычисленное значение возвращается к значению по умолчанию 0s, а вовсе не превращается в "2 секунды" сама по себе. Отрицательная длительность тоже недопустима и отбрасывается точно так же.
.spinner {
animation-name: spin;
animation-duration: 1s;
} - единица измерения указана, один оборот займёт ровно секунду.
Неправильный ход - забыть единицу измерения, думая, что число само по себе воспринимается как секунды:
.spinner {
animation-name: spin;
animation-duration: 1;
} - вся запись невалидна, animation-duration остаётся равным 0s, спиннер вообще не крутится.
animation-iteration-count: сколько раз повторить
animation-iteration-count определяет, сколько раз цикл анимации повторится. По умолчанию это 1 - анимация проигрывается ровно один раз и на этом останавливается, и это частая неожиданность для новичков, которые ждут, что анимация будет крутиться сама по себе (см. FAQ 1). Чтобы анимация повторялась бесконечно, нужно явно указать animation-iteration-count: infinite. Можно указать и дробное число - например 2.5 - тогда анимация остановится ровно на середине третьего цикла: собственная проверка это подтвердила точными числами (при 1-секундном цикле в момент 2.4с прогресс был на 40% третьего цикла, в 2.49с - на 49%). У бесконечного повтора есть своя тонкость: если состояния 0% и 100% в @keyframes описывают РАЗНЫЙ внешний вид (а не просто разные числа для одного и того же свойства, как в полоске загрузки выше, где обнуление на каждом цикле - это и есть задуманный результат), на стыке каждого цикла будет заметен нежелательный скачок - конец одного прохода не переходит плавно в начало следующего (реальный пример такой проблемы - в FAQ 2). Ниже - контраст: одинаковые 0%/100% дают бесшовную петлю, разные - скачок.
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.2); }
100% { transform: scale(1); }
}
.badge { animation: pulse 1s infinite; } - 0% и 100% совпадают, петля бесшовная.
Неправильное ожидание - что стык циклов не имеет значения:
@keyframes pulse {
0% { transform: scale(1); }
100% { transform: scale(1.2); }
}
.badge { animation: pulse 1s infinite; } - 0% и 100% разные, поэтому в конце каждого цикла заметен резкий скачок обратно к scale(1).
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Подключить animation-name и забыть про animation-duration | Длительность по умолчанию равна 0s - анимация технически запускается, но визуально не видна | Всегда указывать длительность явно, с единицей измерения |
| Написать animation-duration без "s" или "ms" (например 2;) | Вся запись невалидна, длительность возвращается к 0s - точно так же, как unitless-число у transition-duration из урока 03 | Всегда писать единицу измерения: 2s или 2000ms |
| Ожидать, что анимация повторяется бесконечно по умолчанию | animation-iteration-count по умолчанию равен 1 - анимация играет всего один раз | Указывать animation-iteration-count: infinite явно, если нужен бесконечный повтор |
| Использовать infinite с несовпадающими 0% и 100% в @keyframes | На стыке каждого цикла виден резкий скачок - конец одного прохода не совпадает с началом следующего | Делать 0% и 100% идентичными, если нужна плавная бесшовная петля |
Шпаргалка
| Запись | Что означает |
|---|---|
| animation-duration: 2s; | Один цикл анимации длится 2 секунды |
| animation-duration: 2; (без единицы) | Невалидно, вся запись отбрасывается, длительность = 0s |
| animation-duration по умолчанию | 0s - без явного значения анимация невидима |
| animation-iteration-count: 3; | Анимация повторится ровно 3 раза и остановится |
| animation-iteration-count: infinite; | Анимация повторяется бесконечно |
| animation-iteration-count: 2.5; | Останавливается ровно на середине третьего цикла |
Коротко: отвечаем на вопросы
Почему моя CSS-анимация проигрывается только один раз, хотя должна повторяться?
Потому что animation-iteration-count по умолчанию равен 1 - анимация играет ровно один раз, а не бесконечно. Если нужен повтор, нужно явно указать animation-iteration-count: infinite (или конкретное число раз). Если же анимацию нужно запустить заново по клику или другому событию, а не просто повторить, реальный приём с Хабра - удалить и заново добавить класс с анимацией через JavaScript (или переключить animation-name на идентичное второе имя), чтобы браузер воспринял это как новую анимацию.
Сделал бесконечную анимацию через infinite, но в конце каждого цикла заметен рывок. Как убрать?
Скорее всего 0% и 100% в @keyframes отличаются - конец одного прохода не совпадает с началом следующего, и на стыке виден скачок. Нужно сделать 0% и 100% идентичными, чтобы петля была бесшовной. Если анимация сложнее (например несколько сторон объекта сменяют друг друга), может понадобиться расписать проценты внутри @keyframes так, чтобы переход между состояниями был плавным на всём протяжении цикла, а не только в одной точке.