Загрузка...

Анимация в CSS

Переходы учили A → B по триггеру. Transform показывал, куда уходит отрисованная box. Анимации задают линию времени: пульс индикатора, бесконечный спиннер, карточки, входящие по очереди — шаги в @keyframes, запуск через animation.

Что такое анимация

Две части: именованный набор keyframe (@keyframes) со стилями на процентах (или from / to) и правило, которое проигрывает это имя с длительностью, необязательной задержкой, числом циклов, направлением, timing function и fill-mode. Браузер интерполирует между остановками keyframe.

Имена должны совпадать строго: animation-name: pulse сработает только если есть @keyframes pulse. Переименуете одно без другого — движения не будет.

Управление анимацией — кратко

📊 Основные части animation

Элемент Роль
@keyframes name { … } Линия времени значений свойств на % / from / to
animation-name Какой набор keyframe проигрывать
animation-duration Длина одного цикла (s или ms)
animation-timing-function Сглаживание внутри цикла (ease, linear, …)
animation-delay Пауза перед первым циклом
animation-iteration-count Сколько циклов (number или infinite)
animation-direction normal, reverse, alternate, alternate-reverse
animation-fill-mode Стили до/после (none, forwards, backwards, both)
animation shorthand name → duration → timing → delay → iteration → direction → fill-mode (типичный порядок)

Не все longhand сразу нужны. Начните с name + duration; для loaderов добавьте infinite, для отката — alternate, когда последний keyframe должен остаться — forwards.

Первая линия времени — спокойный пульс

Opacity и transform щадят отрисовку. Мягкий пульс — классическое первое упражнение с @keyframes.

Мягкий пульс статуса с @keyframes

css
@keyframes pulse {
0%,
100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.55;
transform: scale(0.92);
}
}

.status-dot {
display: inline-block;
width: 0.75rem;
height: 0.75rem;
border-radius: 50%;
background: #16a34a;
animation: pulse 1.4s ease-in-out infinite;
}

0% и 100% совпадают — цикл стыкуется без рывка. infinite крутит цикл дальше — нормально для маленького индикатора, шумно, если анимировать весь hero страницы.

Бесконечное вращение — loader любит linear

Поворот с linear и infinite читается как непрерывный спиннер. Добавьте запасной вариант при prefers-reduced-motion: скрыть или заморозить вращение.

Кольцо loader с бесконечным rotate

css
@keyframes spin {
to {
transform: rotate(360deg);
}
}

.loader {
width: 2rem;
height: 2rem;
border: 3px solid #e5e7eb;
border-top-color: #2563eb;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
.loader {
animation: none;
border-top-color: #e5e7eb;
}
}

to — сокращение для 100%. Старт с дефолтного 0% (без transform) достаточен, когда важен только конец оборота.

Задержка и stagger — одни keyframes, разные старты

Один набор keyframe может двигать много элементов. Stagger через animation-delay: список ощущается поэтапным без трёх разных анимаций.

Поэтапный fade-up у пунктов списка

css
@keyframes fade-up {
from {
opacity: 0;
transform: translateY(0.75rem);
}
to {
opacity: 1;
transform: translateY(0);
}
}

.reveal-list li {
opacity: 0;
animation: fade-up 0.45s ease forwards;
}

.reveal-list li:nth-child(1) { animation-delay: 0s; }
.reveal-list li:nth-child(2) { animation-delay: 0.08s; }
.reveal-list li:nth-child(3) { animation-delay: 0.16s; }

forwards удерживает финальные стили keyframe после цикла — иначе элементы могут вернуться к opacity: 0 из базового правила. Это и есть работа animation-fill-mode.

Fill-mode для одноразового появления

Входные motion часто играют один раз. Fill-mode решает, применяются ли стили до задержки и после последнего кадра.

Появление карточки с fill-mode both

css
@keyframes card-in {
from {
opacity: 0;
transform: translateY(1rem) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}

.card-enter {
animation: card-in 0.5s ease 0.1s both;
}

Shorthand здесь: имя card-in, длительность 0.5s, easing ease, задержка 0.1s, fill-mode both. both берёт первый keyframe на время delay и держит последний после окончания.

Направление, play state и когда не анимировать

animation-direction: alternate — нечётные циклы вперёд, чётные назад; удобно для мягкого bounce без дублирования keyframes. animation-play-state: paused замораживает идущую анимацию (например, пауза декоративного цикла по hover).

Простая смена цвета по hover — по-прежнему transitions. Анимации — когда нужны циклы, многошаговый сценарий или движение не привязано к одному переключению состояния. В keyframes предпочитайте transform и opacity; width, height или top тяжелее и часто дёргают layout.

Попробуйте

  1. Пульс с тремя остановками (0% / 50% / 100%) только по opacity; затем добавьте чуть scale.
  2. Спиннер: spin + linear + infinite; переключите на ease и почувствуйте неровность.
  3. Stagger трёх badge одними fade-up keyframes и задержками 0s, 0.1s, 0.2s — с forwards и без.
  4. Shorthand animation: card-in 0.5s ease 0.15s both на панели; уберите both и посмотрите snap-back.
  5. При prefers-reduced-motion: reduce задайте animation: none (или короткий fade) на декоративных циклах.

Частые ошибки

  • Ждать, что hover A→B fade «зациклится» — это зона animation, а не один transition
  • Опечатка между animation-name и именем в @keyframes — тихий no-op
  • infinite на крупных, навязчивых блоках без паузы или reduced-motion
  • Анимация layout-свойств (width, margin, top), когда хватило бы transform/opacity
  • Нет forwards / both на одноразовых reveal с opacity: 0 в базовом правиле

Итог

  • @keyframes задают линию времени; animation (или longhands) её проигрывают
  • iteration, direction, delay и fill-mode — для циклов, отката, stagger и «липкого» финала
  • Предпочитайте transform/opacity; уважайте prefers-reduced-motion на декоративном motion
  • Transitions для простых смен состояния; animations для многошагового и повторяющегося
  • Далее в Effects & Motion: CSS Filters

🧠 Проверьте Свои Знания

Готов к Началу

Проверьте Свои Знания

Бросьте себе вызов с помощью этой интерактивной викторины и узнайте, насколько хорошо вы понимаете тему

❓
7
Вопросы
🎯
70%
Для Прохождения
♾️
∞
Время
🔄
∞
Попытки

📝 Инструкции

  • Внимательно прочитайте каждый вопрос
  • Выберите лучший ответ на каждый вопрос
  • Вы можете пересдавать тест столько раз, сколько захотите
  • Ваш прогресс будет показан вверху