CSS: анимации
Введение: движение, которое объясняет интерфейс
Хорошая анимация в UI работает как жест руками в разговоре: не отвлекает, а помогает быстрее понять смысл.
Если элементы двигаются осознанно, пользователь сразу считывает, что произошло и что делать дальше.
Если элементы двигаются осознанно, пользователь сразу считывает, что произошло и что делать дальше.
Без анимаций интерфейс может казаться "мертвым", а без правил анимации - хаотичным и утомляющим.
Поэтому CSS-анимации важны не как украшение, а как инструмент понятного UX.
Поэтому CSS-анимации важны не как украшение, а как инструмент понятного UX.
💡 Совет:
Сначала определяйте смысл движения, потом подбирайте эффект.
✅ Вывод:
Анимация в CSS должна усиливать понятность, а не создавать шум.
Проблема -> решение
Проблема:
Элементы появляются резко, пользователь не замечает изменения состояния, а бесконечные эффекты начинают раздражать.
Решение:
Строить анимацию по правилам: сценарий через
@keyframes, управляемые параметры animation-*, осознанные длительности и обязательный учет prefers-reduced-motion.✅ Вывод:
Системная анимация снижает когнитивную нагрузку и делает интерфейс предсказуемым.
Чем помогает и как работает
CSS-анимации помогают:
- показать причинно-следственную связь: "нажал -> изменилось";
- подсветить важные изменения без агрессивного визуала;
- снизить ощущение "подвисания" при загрузке;
- сделать интерфейс целостным за счет единого ритма движения.
Как это работает:
- Шаг 1: определяете пользовательский сценарий, где движение реально полезно.
- Шаг 2: описываете ключевые кадры (
@keyframes) или выбираете transition для простого перехода. - Шаг 3: задаете длительность и кривую скорости, чтобы движение было читабельным.
- Шаг 4: ограничиваете повторы и избегаете бесконечной анимации без необходимости.
- Шаг 5: проверяете влияние на UX: не мешает ли движение читать и выполнять действия.
- Шаг 6: добавляете
prefers-reduced-motionи fallback-поведение. - Шаг 7: фиксируете motion-правила в дизайн-системе команды.
✅ Вывод:
Анимация полезна только тогда, когда встроена в сценарий и контролируется правилами.
Ключевые термины (простыми словами)
- Animation (анимация) - изменение CSS-свойств во времени по сценарию.
- @keyframes (ключевые кадры) - этапы анимации от старта к финалу.
- Duration (длительность) - сколько времени длится один цикл.
- Delay (задержка) - пауза перед началом.
- Timing function (кривая скорости) - как ускоряется и замедляется движение.
- Iteration count (число повторов) - сколько раз проигрывается анимация.
- Direction (направление) - в одну сторону или туда-обратно.
- Fill mode (сохранение состояния) - что остается до/после анимации.
- Play state (состояние проигрывания) - идет анимация или на паузе.
- Reduced motion (уменьшение движения) - режим доступности для пользователей, которым тяжело от motion.
1. @keyframes - сценарий анимации
Назначение:
Описать, как именно элемент меняется на разных этапах.
Простыми словами:
Это "раскадровка" движения: от какого состояния к какому идет элемент.
Для новичка:
Если не задать
@keyframes, то CSS не понимает, какую последовательность менять.Аналогия:
Как сценарий фильма с ключевыми сценами.
Пример:
@keyframes pulse { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.06); opacity: 0.75; }}🔎 Как это происходит на практике:
- Команда решает, что бейдж "Новый" должен мягко привлекать внимание.
- Дизайнер задает начальное и конечное состояние.
- Разработчик переносит это в keyframes.
Характеристики:
- ✅ позволяет строить сложный сценарий;
- ✅ поддерживает промежуточные кадры 25/50/75%;
- ✅ дает полный контроль над движением.
Когда использовать:
Когда эффект нельзя выразить одним изменением состояния.
✅ Вывод:
@keyframes - фундамент любой осознанной CSS-анимации.2. animation-name, animation-duration и шорткат animation
Назначение:
Подключить сценарий к элементу и задать длительность.
Простыми словами:
Вы "назначаете" элементу анимацию и говорите, как быстро ее проигрывать.
Для новичка:
Без duration анимация может быть незаметной или выглядеть как резкий скачок.
Аналогия:
Выбрали трек и установили его длину.
Пример:
.badge { animation-name: pulse; animation-duration: 800ms;} .loader { animation: spin 1s linear infinite;}🔎 Как это происходит на практике:
- В UI-компоненте создают библиотечный класс
.is-loading. - Через шорткат
animationзадают сценарий одним выражением. - Эффект переиспользуется в разных частях приложения.
Характеристики:
- ✅ быстрое подключение keyframes;
- ✅ шорткат сокращает код;
- ✅ удобно стандартизировать длительности.
Когда использовать:
Всегда при запуске keyframes-анимации на элементе.
✅ Вывод:
name + duration - обязательный минимум для управляемой анимации.3. animation-timing-function - характер скорости
Назначение:
Определить, как ощущается движение во времени.
Простыми словами:
Можно сделать эффект ровным, мягким или более резким.
Для новичка:
ease обычно безопаснее, чем linear, для интерфейсных микроэффектов.Аналогия:
Как разгон и торможение автомобиля: плавно или без амортизации.
Пример:
.card { animation: fade-in 280ms ease-out;} .accent { animation: pulse 700ms cubic-bezier(0.2, 0.8, 0.2, 1);}🔎 Как это происходит на практике:
- Дизайнер жалуется: "анимация слишком механическая".
- Разработчик меняет linear на ease-out.
- Эффект начинает восприниматься естественно.
Характеристики:
- ✅ влияет на эмоциональное восприятие;
- ✅ помогает согласовать motion-стиль бренда;
- ✅ при плохом выборе кривая делает UI дерганым.
Когда использовать:
Для всех анимаций, где важен "характер" движения.
✅ Вывод:
Одна и та же анимация с разной кривой ощущается как разные интерфейсы.
4. animation-delay и последовательности (stagger)
Назначение:
Запускать элементы не одновременно, а в логичном порядке.
Простыми словами:
Сначала появляется первый блок, потом второй, потом третий.
Для новичка:
Небольшая задержка (50-150ms между элементами) часто делает появление чище.
Аналогия:
Выход участников на сцену по очереди, а не всей толпой.
Пример:
.card { animation: fade-in 300ms ease forwards;} .card:nth-child(2) { animation-delay: 80ms; }.card:nth-child(3) { animation-delay: 160ms; }🔎 Как это происходит на практике:
- Каталог курсов рендерит 12 карточек.
- Без stagger интерфейс "вспыхивает" сразу.
- С задержками пользователь легче считывает структуру.
Характеристики:
- ✅ улучшает визуальный ритм;
- ✅ помогает иерархии контента;
- ✅ в избытке может замедлять UX.
Когда использовать:
При поочередном появлении списков, меню, карточек.
✅ Вывод:
Delay полезен, когда помогает чтению интерфейса, а не тормозит его.
5. Повторы и управление: animation-iteration-count, direction, play-state
Назначение:
Контролировать количество циклов, направление и паузу анимации.
Простыми словами:
Можно крутить бесконечно, ограничить в 3 раза или поставить на паузу при hover.
Для новичка:
Если эффект не про загрузку, бесконечный цикл чаще вреден.
Аналогия:
Музыка: можно повторять трек один раз, по кругу или ставить на паузу.
Пример:
.hint { animation: pulse 700ms ease-in-out 3 alternate;} .hint:hover { animation-play-state: paused;}🔎 Как это происходит на практике:
- Подсказка должна привлечь внимание и успокоиться.
- Команда ставит 3 повтора вместо infinite.
- На hover эффект ставится на паузу, чтобы прочитать текст.
Характеристики:
- ✅ точный контроль жизненного цикла эффекта;
- ✅ меньше раздражения от постоянного движения;
- ✅ помогает управлять вниманием пользователя.
Когда использовать:
Для подсказок, бейджей, акцентных индикаторов и hover-пауз.
✅ Вывод:
Управление циклами и паузой критично для "здорового" motion.
6. animation-fill-mode - что остается после проигрывания
Назначение:
Сохранить начальное или конечное состояние после анимации.
Простыми словами:
Элемент может "остаться в финале", а не прыгнуть обратно.
Для новичка:
Для анимации появления часто нужен
forwards.Аналогия:
Финальный кадр презентации остается на экране.
Пример:
@keyframes fade-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); }} .card--enter { animation: fade-in 300ms ease forwards;}🔎 Как это происходит на практике:
- Карточка курса появляется при фильтрации.
- Без
forwardsэлемент может визуально "откатиться". - С fill-mode финальное состояние фиксируется.
Характеристики:
- ✅ устраняет визуальные скачки после анимации;
- ✅ полезен для enter/exit сценариев;
- ✅ снижает количество дополнительных стилей.
Когда использовать:
Когда финальное состояние должно сохраниться после проигрывания.
✅ Вывод:
fill-mode управляет "послевкусием" анимации и стабилизирует UI.7. Производительность: что анимировать безопаснее
Назначение:
Снизить риск подтормаживаний и "тяжелых" эффектов.
Простыми словами:
Лучше анимировать
transform и opacity, а не свойства, которые сильно пересчитывают layout.Для новичка:
Если анимация начинает лагать, сначала проверьте, какие свойства меняются.
Аналогия:
Легче двигать предметы на колесиках, чем перестраивать весь шкаф.
Пример:
.item { transition: transform 200ms ease, opacity 200ms ease;} .item:hover { transform: translateY(-4px); opacity: 0.95;}🔎 Как это происходит на практике:
- На странице 50 карточек, и hover тормозит.
- Команда убирает анимацию ширины/позиционирования.
- После перехода на transform/opacity интерфейс работает плавнее.
Характеристики:
- ✅ лучше масштабируется на длинных списках;
- ✅ меньше визуальных артефактов;
- ✅ проще поддерживать единый motion-стандарт.
Когда использовать:
Всегда, когда нужно анимировать много элементов или сложные списки.
✅ Вывод:
Правильный выбор анимируемых свойств важнее, чем "красивый" эффект.
8. Доступность: prefers-reduced-motion как обязательный стандарт
Назначение:
Уважать настройки пользователей, которым тяжело от движения.
Простыми словами:
Если человек просит меньше движения, интерфейс должен это учитывать.
Для новичка:
Reduced-motion - не опция "по желанию", а базовый слой доступности.
Аналогия:
Как приглушить свет в комнате, если яркость вызывает дискомфорт.
Пример:
@media (prefers-reduced-motion: reduce) { .loader, .badge, .card--enter { animation: none !important; transition: none !important; }}🔎 Как это происходит на практике:
- QA включает reduced-motion в системе.
- Команда проверяет, что пульсации и вращения отключаются.
- Интерфейс остается функциональным без движения.
Характеристики:
- ✅ улучшает комфорт и доступность;
- ✅ снижает риск негативной реакции на motion;
- ✅ показывает зрелость продукта.
Когда использовать:
В любом проекте, где есть анимации и переходы.
✅ Вывод:
Хорошая анимация всегда учитывает сценарий "без анимации".
Must-know факты (часто спрашивают и часто путают)
- Без
@keyframesCSS-анимация не знает сценарий движения. animationиtransitionрешают разные задачи: сценарий vs переход состояния.transition: allчасто ухудшает предсказуемость и производительность.- Бесконечная анимация допустима в основном для загрузчиков и системных индикаторов.
forwardsвfill-modeнужен, когда финальное состояние должно сохраниться.- Motion нужно тестировать вместе с keyboard/focus сценариями.
prefers-reduced-motion- обязательная часть доступности.- Если движение не помогает понять действие, его лучше убрать.
✅ Вывод:
Эти восемь правил закрывают большинство практических ошибок по CSS-анимации.
Сравнение: transition vs animation
| Подход | Когда использовать | Плюсы | Риск |
|---|---|---|---|
transition | Простая смена состояния (hover/focus) | Легко внедрить, мало кода | Сложные сценарии трудно описать |
animation + @keyframes | Сценарное движение с этапами | Гибкость и контроль | Легко переусложнить |
| Бесконечная анимация | Загрузка/статус процесса | Ясный сигнал "идет работа" | Раздражение, если использовать везде |
| Reduced-motion fallback | Любой motion в продукте | Доступность и комфорт | Без проверки может быть нерабочим |
Часто спрашивают на собеседованиях
- Когда выбрать
transition, а когда@keyframes? - Почему
transition: allсчитают плохой практикой? - Какие свойства безопаснее анимировать и почему?
- Зачем нужен
animation-fill-mode: forwards? - Когда допустима бесконечная анимация в UI?
- Как правильно внедрять
prefers-reduced-motion? - Какие типовые ошибки чаще всего встречаются в motion-дизайне на фронте?
✅ Вывод:
На собеседованиях обычно проверяют связь анимации с UX, производительностью и доступностью.
Типичные ошибки
Ошибка 1: Анимация без цели
❌ Неправильно:
Добавлять движение "просто чтобы красиво".
✅ Правильно:
Анимировать только те изменения, которые помогают понять состояние.
Почему:
Лишний motion отвлекает и ухудшает читаемость интерфейса.
Ошибка 2: transition: all
❌ Неправильно:
Анимировать все свойства подряд.
✅ Правильно:
Явно указывать целевые свойства (
transform, opacity).Почему:
all создает непредсказуемое и часто тяжелое поведение.Ошибка 3: Бесконечная пульсация всего экрана
❌ Неправильно:
Ставить
infinite на обычные карточки и кнопки.✅ Правильно:
Ограничивать количество повторов или включать цикл только в загрузчиках.
Почему:
Постоянное движение быстро раздражает пользователя.
Ошибка 4: Нет prefers-reduced-motion
❌ Неправильно:
Всегда проигрывать анимации независимо от системных настроек.
✅ Правильно:
Отключать или упрощать motion в режиме
reduce.Почему:
Это важный стандарт доступности.
Ошибка 5: Резкие длительности и кривые
❌ Неправильно:
Слишком быстрые или дерганые эффекты без теста UX.
✅ Правильно:
Использовать умеренные duration и согласованные timing-function.
Почему:
Характер движения напрямую влияет на восприятие качества продукта.
Ошибка 6: Забыт fill-mode при enter-анимации
❌ Неправильно:
Элемент появляется и "откатывается" обратно.
✅ Правильно:
Для сценариев появления использовать
forwards или both.Почему:
Иначе финальное состояние не фиксируется и UI выглядит сломанным.
Best Practices
- Держите motion-гайд: длительности, кривые, допустимые эффекты.
- Для микроинтеракций начинайте с
transformиopacity. - Используйте анимацию как объяснение состояния, а не украшение ради украшения.
- Проверяйте сценарии reduced-motion в каждом релизе.
- Ограничивайте бесконечные эффекты только функциональными индикаторами.
- Если эффект сложно объяснить, вероятно он не нужен.
Заключение
CSS-анимации дают интерфейсу живость, но их сила в контроле и уместности.
Когда движение осмысленно, пользователь быстрее понимает происходящее и увереннее взаимодействует с продуктом.
Когда движение осмысленно, пользователь быстрее понимает происходящее и увереннее взаимодействует с продуктом.
Ключевые мысли
- Анимация должна объяснять, а не отвлекать.
@keyframesиanimation-*дают полный контроль над сценарием.- Доступность и производительность обязательны для любого motion-решения.