@keyframes - это правило CSS, которое описывает состояния элемента в разные моменты анимации: 0% - начало, 100% - конец, а между ними можно добавить любые промежуточные точки. Для простых анимаций с двумя состояниями проценты можно заменить словами from и to. Само по себе правило ничего не анимирует - его нужно подключить к элементу через animation, а это тема следующего урока.
Попробуй прямо сейчас: у мяча всего три описанных состояния - слева и синий (0%), справа и оранжевый (50%), снова слева и снова синий (100%) - а браузер сам плавно рассчитывает всё, что между ними. Само подключение сделано строкой animation: bounce 3s ease-in-out infinite - имя анимации, её длительность и число повторов разберём подробно в следующих уроках, здесь это только то, что нужно, чтобы @keyframes ожили. Попробуй добавить ещё одну точку - 25% { left: 100px; } - и посмотри, как мяч подстроит движение под новую промежуточную остановку.
from и to: два состояния
Если у анимации всего два состояния - начальное и конечное, - проценты можно заменить более понятными словами: from значит буквально то же самое, что 0%, а to - то же самое, что 100%. Собственная проверка подтвердила: @keyframes с from/to и точно такой же набор с 0%/100% в любой момент времени дают абсолютно одинаковый результат - это не приближение, а полное совпадение. Есть и менее очевидный момент: если не указать 0%/from или 100%/to вообще, браузер не считает это ошибкой - он берёт недостающую границу из ТЕКУЩЕГО, не анимированного стиля элемента. Собственная проверка показала это на @keyframes с одной-единственной точкой 50% { width: 200px; }: элемент с изначальным width: 60px плавно идёт 60px -> 200px -> 60px, хотя ни 0%, ни 100% в правиле вообще не упомянуты.
@keyframes fade-in {
from { opacity: 0; }
to { opacity: 1; }
} - ровно то же самое, что 0% { opacity: 0; } и 100% { opacity: 1; }.
Неправильный ход - придумывать свои слова вместо from/to:
@keyframes fade-in {
start { opacity: 0; }
end { opacity: 1; }
} - start и end не являются ключевыми словами CSS, браузер просто ИГНОРИРУЕТ эти строки - у анимации не остаётся ни одной настоящей точки, и элемент визуально не меняется вообще.
Из истории
Предложить transitions и @keyframes на W3C Дэйв Хайетт из WebKit успел ещё в ноябре 2007 года, но реально заработала эта функция куда позже: 5 февраля 2009 года в официальном блоге WebKit другой инженер, Дин Джексон (Dean Jackson), объявил, что @keyframes и animation теперь по-настоящему работают в WebKit - с уточнением, что на iPhone эта возможность была доступна уже с версии OS 2.0. Оригинальный пост в блоге WebKit.
Проценты: любое число промежуточных состояний
Главное преимущество процентов перед from/to - можно описать сколько угодно промежуточных остановок, а не только начало и конец, как в демо выше с мячом (0%, 50%, 100%). Один и тот же процент можно даже указать в правиле несколько раз - собственная проверка показала, что это не ошибка: свойства из обоих блоков СКЛАДЫВАЮТСЯ, а если одно и то же свойство повторяется, побеждает более позднее объявление - точно как в обычном каскаде CSS. А ещё несколько процентов можно перечислить через запятую перед одним и тем же блоком стилей, если у них одинаковый набор свойств - собственная проверка подтвердила это на классическом приёме "дрожания" (shake): 10%, 30%, 50%, 70%, 90% сдвигают элемент в одну сторону, а 20%, 40%, 60%, 80% - в другую, и все девять точек описаны всего двумя блоками кода.
@keyframes shake {
10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); }
20%, 40%, 60%, 80% { transform: translateX(10px); }
} - девять точек дрожания описаны всего двумя блоками стилей.
Неправильное ожидание - что повторение процента полностью заменяет предыдущий блок:
@keyframes move {
0% { top: 0px; left: 0px; }
50% { top: 30px; left: 20px; }
50% { top: 10px; }
} - на 50% секунде left всё равно останется 20px (из первого блока), а top станет 10px (из второго) - свойства не заменяют друг друга целиком, а складываются по каждому свойству отдельно.
Частые ошибки новичков
| Ошибка | Что происходит | Как исправить |
|---|---|---|
| Написать @keyframes и ждать, что элемент сам начнёт двигаться | @keyframes только ОПИСЫВАЕТ состояния - само по себе оно ничего не анимирует, пока не подключено через animation-name/animation к элементу | Подключать анимацию к элементу - подробно об этом в следующем уроке |
| Придумывать свои слова вместо from/to (например start/end) | Единственные допустимые ключевые слова - from (=0%) и to (=100%); всё остальное браузер просто игнорирует, без ошибки | Использовать только from/to или проценты - ничего третьего в качестве селектора кадра не существует |
| Указать animation-name, но забыть длительность | animation-duration по умолчанию равен 0s - при нуле секунд анимация вообще не запускается (не мгновенно, а буквально никак) | Всегда указывать длительность - через animation-duration или в сокращённой записи animation (следующие уроки) |
| Думать, что повторный процент в @keyframes - синтаксическая ошибка | Это не ошибка: свойства из обоих блоков складываются, а при совпадении свойства побеждает более позднее объявление - как обычный каскад CSS | Не дублировать процент случайно при копировании кода - иначе можно получить неожиданную смесь двух блоков |
Шпаргалка
| Запись | Что означает |
|---|---|
| from { ... } / to { ... } | То же самое, что 0% { ... } и 100% { ... } |
| 0%, 25%, 50%, 100% { ... } | Любое число промежуточных состояний, не только начало и конец |
| Нет 0%/from или 100%/to | Недостающая граница берётся из ТЕКУЩЕГО (не анимированного) стиля элемента |
| Один и тот же процент дважды | Свойства складываются, при повторении свойства побеждает более позднее объявление |
| 10%, 30%, 50% { ... } | Несколько процентов через запятую могут делить один блок стилей |
| @keyframes само по себе | Ничего не анимирует - нужно подключить через animation-name/animation (следующий урок) |
Коротко: отвечаем на вопросы
Как сделать эффект "дрожания" (shake) с помощью @keyframes?
Описать несколько процентов через запятую с одним и тем же смещением: например, 10%, 30%, 50%, 70%, 90% { transform: translateX(-10px); } и 20%, 40%, 60%, 80% { transform: translateX(10px); } внутри одного @keyframes. Получается быстрое чередование влево-вправо на девяти точках, хотя описаны они всего двумя блоками стилей.
Я написал @keyframes и указал animation-name, но анимация не проигрывается. В чём дело?
Скорее всего не задана длительность. animation-name сам по себе ничего не запускает - обязательно нужен ещё animation-duration (или сокращённая запись animation с указанием времени). Без него длительность по умолчанию равна 0 секунд, и анимация не создаётся вообще, а не просто проигрывается мгновенно.