Keyframes
@keyframes— правило CSS, которое определяет последовательность кадров анимации. Свойствоanimationпривязывает эту анимацию к элементу, задавая длительность, плавность, повторения и другие параметры.
Зачем нужно
Transition анимирует только между двумя состояниями (A → B). @keyframes позволяет создавать сложные многошаговые анимации (A → B → C → D...), которые могут запускаться автоматически, повторяться бесконечно и работать независимо от пользовательских действий.
Где используется
- Загрузочные спиннеры и индикаторы
- Анимации появления элементов (fade-in, slide-in)
- Пульсирующие уведомления
- Бегущие строки и маркизы
- Сложные декоративные эффекты
Предпосылки
- transition -- плавные переходы — базовые переходы
- transform -- rotate, scale, translate — трансформации для анимации
Определение @keyframes
/* Два ключевых кадра */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
/* Несколько ключевых кадров через проценты */
@keyframes bounce {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-30px);
}
100% {
transform: translateY(0);
}
}
/* Множество шагов */
@keyframes colorCycle {
0% { background-color: #ff6b6b; }
25% { background-color: #ffd93d; }
50% { background-color: #6bcb77; }
75% { background-color: #4d96ff; }
100% { background-color: #ff6b6b; }
}
Свойства animation
animation-name
.element {
animation-name: fadeIn; /* Имя @keyframes */
animation-name: none; /* Отключить */
}
animation-duration
.element {
animation-duration: 1s; /* 1 секунда */
animation-duration: 300ms; /* 300 миллисекунд */
}
animation-timing-function
.element {
animation-timing-function: ease; /* По умолчанию */
animation-timing-function: linear; /* Равномерно */
animation-timing-function: ease-in; /* Медленный старт */
animation-timing-function: ease-out; /* Медленный конец */
animation-timing-function: ease-in-out; /* Плавно */
animation-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* Кастом */
animation-timing-function: steps(6); /* Покадрово */
}
animation-delay
.element {
animation-delay: 0s; /* Без задержки */
animation-delay: 500ms; /* Полсекунды */
animation-delay: -200ms; /* Начать «из середины» */
}
animation-iteration-count
.element {
animation-iteration-count: 1; /* Один раз (по умолчанию) */
animation-iteration-count: 3; /* Три раза */
animation-iteration-count: infinite; /* Бесконечно */
}
animation-direction
.element {
animation-direction: normal; /* 0% → 100% */
animation-direction: reverse; /* 100% → 0% */
animation-direction: alternate; /* 0% → 100% → 0% → ... */
animation-direction: alternate-reverse; /* 100% → 0% → 100% → ... */
}
animation-fill-mode
.element {
/* Что происходит ДО и ПОСЛЕ анимации */
animation-fill-mode: none; /* Вернуть к исходному (по умолчанию) */
animation-fill-mode: forwards; /* Остаться в конечном состоянии */
animation-fill-mode: backwards; /* Применить начальный кадр до старта (при delay) */
animation-fill-mode: both; /* forwards + backwards */
}
forwards— самый частый. Без него элемент «прыгнет» обратно в исходное состояние после анимации.
animation-play-state
.element {
animation-play-state: running; /* Играет */
animation-play-state: paused; /* На паузе */
}
/* Пауза при наведении */
.element:hover {
animation-play-state: paused;
}
Сокращённая запись (shorthand)
.element {
/* name duration timing delay count direction fill-mode play-state */
animation: fadeIn 1s ease 0s 1 normal forwards running;
/* Минимум: имя и длительность */
animation: fadeIn 1s;
/* Типичный набор */
animation: slideIn 500ms ease-out forwards;
/* Бесконечная */
animation: spin 2s linear infinite;
/* Несколько анимаций */
animation:
fadeIn 500ms ease forwards,
slideUp 600ms ease-out 200ms forwards;
}
Практические примеры
Fade-in при загрузке
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.section {
animation: fadeIn 600ms ease-out forwards;
}
/* Каскадная задержка для элементов */
.section:nth-child(1) { animation-delay: 0ms; }
.section:nth-child(2) { animation-delay: 100ms; }
.section:nth-child(3) { animation-delay: 200ms; }
Спиннер
@keyframes spin {
to {
transform: rotate(360deg);
}
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e9ecef;
border-top-color: #007bff;
border-radius: 50%;
animation: spin 800ms linear infinite;
}
Пульсация
@keyframes pulse {
0%, 100% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.05);
opacity: 0.8;
}
}
.notification-dot {
width: 12px;
height: 12px;
background: #dc3545;
border-radius: 50%;
animation: pulse 2s ease-in-out infinite;
}
Bounce-вход
@keyframes bounceIn {
0% {
transform: scale(0.3);
opacity: 0;
}
50% {
transform: scale(1.05);
}
70% {
transform: scale(0.9);
}
100% {
transform: scale(1);
opacity: 1;
}
}
.modal {
animation: bounceIn 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55) forwards;
}
Покадровая анимация (спрайты)
@keyframes walk {
from { background-position: 0 0; }
to { background-position: -640px 0; }
}
.character {
width: 80px;
height: 100px;
background: url("sprite.png");
animation: walk 800ms steps(8) infinite;
}
Каскадная задержка через CSS-переменные
@keyframes fadeUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.list-item {
opacity: 0;
animation: fadeUp 400ms ease forwards;
animation-delay: calc(var(--i, 0) * 100ms);
}
<ul>
<li class="list-item" style="--i: 0">Первый</li>
<li class="list-item" style="--i: 1">Второй</li>
<li class="list-item" style="--i: 2">Третий</li>
</ul>
Частые ошибки
- Забыли
animation-fill-mode: forwards— элемент «прыгает» назад после анимации - Анимация не запускается — проверьте имя:
animation-nameдолжно точно совпадать с@keyframes - Дублирование
from/toи процентов:/* ОШИБКА */ @keyframes bad { from { opacity: 0; } 0% { opacity: 0.5; } /* Конфликт! */ } - Анимация
height: auto— CSS не может анимироватьauto. Используйтеmax-heightилиtransform: scaleY - Слишком много анимаций одновременно — перегружает GPU и тормозит UI
Практика
- Создать спиннер через
@keyframes+rotate - Сделать fade-in анимацию с каскадной задержкой
- Создать пульсирующий элемент с
infinite+alternate - Сделать покадровую анимацию через
steps - Создать bounce-эффект с несколькими ключевыми кадрами
Связанные темы
- transition -- плавные переходы — простые переходы между состояниями
- transform -- rotate, scale, translate — трансформации внутри keyframes
- Практика анимаций — готовые рецепты и паттерны
- calc() — вычисление задержек