Основы анимации
Принципы хорошей анимации, прогресс → easing → интерполяция, какой инструмент выбрать, минимальная база.
Обновлено
Что делает анимацию хорошей
Хорошая анимация объясняет: откуда появился элемент, куда ушёл, что изменилось, что ваше действие сработало. Плохая только задерживает пользователя. Прежде чем говорить об инструментах — 5 идей, которые отличают «работает» от «выглядит профессионально»:
| Принцип | Что значит | Пример |
|---|---|---|
| короткая длительность | 150–300 мс для интерфейса, редко больше 500 мс | выпадающее меню появляется за 200 мс |
| easing | ничто в реальности не движется линейно | ease-out при появлении |
| stagger | элементы списка стартуют по очереди, а не все сразу | карточки появляются одна за другой с шагом 60 мс |
| малое расстояние | сдвиги на 8–24 px, а не через весь экран | y: 16 → 0 + opacity: 0 → 1 |
| непрерывность | элемент превращается, а не исчезает и появляется снова | карточка, разворачивающаяся в страницу подробностей |
И техническое правило: анимируйте transform и opacity — см. Переходы и анимации в CSS.
Три числа за любой анимацией
Любая библиотека под капотом делает одно и то же вычисление на каждом кадре (~60 в секунду):
- прогресс
tот 0 до 1 = прошедшее время / длительность; - easing: превращает
tв «ощущаемый» прогресс —easeOutCubic(t) = 1 - (1 - t)³; - интерполяция (lerp): текущее значение =
start + (end - start) × прогресс.
const lerp = (a, b, t) => a + (b - a) * t
const easeOutCubic = t => 1 - (1 - t) ** 3
lerp(0, 100, easeOutCubic(0.5)) // 87.5 — на середине времени уже почти у целиПружины (Motion) не имеют фиксированной длительности: они моделируют пружину с жёсткостью и затуханием — поэтому выглядят естественно и прерываются без рывка.
Инструменты — какой и когда
| Инструмент | Для | Размер | Когда |
|---|---|---|---|
| CSS (transition, @keyframes) | hover, фокус, простые появления | 0 КБ | всегда в первую очередь |
| View Transitions API | переходы между состояниями / страницами | 0 КБ | морфинг между списком и деталями |
Motion (motion/react) |
декларативные анимации в React: появление, уход, layout, жесты, прокрутка | средний | по умолчанию в React |
| GSAP | сложные таймлайны, сторителлинг на прокрутке, анимированный текст, SVG | средний | лендинги, имиджевые сайты |
| Lottie | анимации, нарисованные в After Effects | разный | анимированные иллюстрации |
| Three.js / R3F | 3D, WebGL | большой | 3D-впечатления |
Самая короткая база, чтобы начать
Три рецепта покрывают 80% того, что вы видите на «красивых» сайтах:
1. Появление при прокрутке (только CSS, без JS):
.reveal {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry 0% entry 60%;
}
@keyframes reveal {
from { opacity: 0; transform: translateY(24px); }
}2. Список, который появляется со stagger (Motion):
<motion.ul initial="hidden" animate="show" variants={{ show: { transition: { delayChildren: stagger(0.06) } } }}>
{items.map(item => (
<motion.li key={item.id} variants={{ hidden: { opacity: 0, y: 16 }, show: { opacity: 1, y: 0 } }} />
))}
</motion.ul>3. Отклик на взаимодействие (Motion):
<motion.button whileHover={{ scale: 1.03 }} whileTap={{ scale: 0.97 }}>Сохранить</motion.button>Подробности — в уроках Motion и GSAP; полные примеры — в Интересные примеры.
Доступность
Учитывайте prefers-reduced-motion: в CSS через media query, в Motion через useReducedMotion() или <MotionConfig reducedMotion="user">, в GSAP через gsap.matchMedia(). Не анимируйте то, что мигает чаще 3 раз в секунду.
Коротко
- Коротко (150–300 мс),
ease-out, stagger, малые расстояния, толькоtransformиopacity. - Любая анимация = прогресс → easing → интерполяция.
- Сначала CSS; Motion для React; GSAP для таймлайнов и сложной прокрутки; учитывайте reduced motion.