Переходы и анимации
transition или @keyframes, easing, что дёшево анимировать, prefers-reduced-motion.
Обновлено
Что такое переходы и анимации
Движение в интерфейсе — это не украшение, у него есть задача: показать, что изменилось, откуда появился элемент и что ваше действие сработало. CSS даёт два инструмента:
| Transition | Animation (@keyframes) |
|
|---|---|---|
| Запускается | когда свойство меняется (hover, новый класс) | сама, при появлении или по кругу |
| Состояния | от A к B | сколько угодно шагов (0%, 50%, 100%) |
| Когда | hover, фокус, открытие / закрытие, обратная связь | лоадер, появление на странице, привлечение внимания |
Transition
.btn {
transition: background-color 150ms ease, transform 150ms ease;
}
.btn:hover {
background-color: var(--accent-hover);
transform: translateY(-1px);
}transition: <свойство> <длительность> <easing> <задержка>. Избегайте transition: all — анимируются и ненужные свойства (и это дорого).
@keyframes и animation
@keyframes fade-in {
from { opacity: 0; transform: translateY(8px); }
to { opacity: 1; transform: none; }
}
.toast {
animation: fade-in 200ms ease-out both;
}| Свойство | Роль |
|---|---|
animation-duration |
сколько длится |
animation-timing-function |
кривая скорости |
animation-iteration-count |
сколько раз (infinite для лоадера) |
animation-fill-mode: both |
сохраняет начальный стиль до и конечный после |
Easing — кривая скорости
| Easing | Ощущение | Когда |
|---|---|---|
ease-out |
быстро стартует, замедляется | появляющиеся элементы — самое естественное |
ease-in |
медленно стартует, ускоряется | исчезающие элементы |
ease-in-out |
медленно – быстро – медленно | перемещение из одного места в другое |
linear |
постоянная | вращение, прогресс, лоадеры |
Длительность: 100–200 мс для обратной связи (hover), 200–300 мс для появления, редко больше 400 мс. Длинные анимации делают интерфейс медленным.
Что анимировать — производительность
Анимируйте только transform и opacity: они считаются на GPU, без layout. width, height, top, margin вызывают layout на каждом кадре → дёрганая анимация. Объяснение — в уроке Как браузер отрисовывает страницу.
| Вместо | Используйте |
|---|---|
left: 0 → 100px |
transform: translateX(100px) |
width: 0 → 100% (полоса прогресса) |
transform: scaleX(0 → 1) |
display: none ↔ block |
opacity + visibility или @starting-style |
Уважайте настройку пользователя
У некоторых людей бывает укачивание или вестибулярная чувствительность, и они включают в системе «уменьшить движение». Обязательно:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}В Tailwind: motion-safe:animate-… / motion-reduce:transition-none.
Современное: появление из display: none
.dialog[open] {
opacity: 1;
transition: opacity 200ms, display 200ms allow-discrete;
@starting-style { opacity: 0; }
}@starting-style задаёт состояние «до появления» — можно анимировать элементы, которые только что вышли из display: none. Для переходов между страницами есть View Transitions API.
Дальше
Анимации в React (Motion), таймлайны и скролл (GSAP) и полные примеры — в теме Анимации.
Коротко
- Transition = от A к B при изменении; animation =
@keyframes, запускается сама. ease-outпри появлении, 150–300 мс; толькоtransformиopacity.prefers-reduced-motionобязателен.