Перейти к содержанию
Innovialabs

Анимации на сайте: CSS или JavaScript, GSAP и Motion

Практика3 мин

Коротко

Простые состояния (hover, появление, раскрытие) делайте на CSS, сложные последовательности и анимации по прокрутке — на GSAP или Motion; анимируйте только transform и opacity и отключайте движение при prefers-reduced-motion.

Короткий ответ

  • CSS transitions и keyframes — для hover, фокуса, открытия меню, появления элементов, бесконечных лоадеров. Это дёшево, не требует библиотек и работает даже до загрузки JavaScript.
  • GSAP — для сложных таймлайнов, синхронизации многих элементов, анимаций по прокрутке с закреплением блоков, анимации SVG.
  • Motion — для React-интерфейсов: анимации появления и исчезновения компонентов, перестановки в списках, жесты, переходы между состояниями. Есть и версия для обычного JavaScript.

Правило выбора простое: если анимацию можно описать как «из состояния А в состояние Б по событию», берите CSS. Если нужны цепочки, управление временем, привязка к прокрутке или физика — JavaScript-библиотеку.

Какие свойства анимировать дёшево

Браузер рисует кадр в несколько этапов: layout (расчёт размеров), paint (отрисовка пикселей) и composite (склейка слоёв). Чем раньше этап затрагивает анимация, тем она дороже.

СвойствоЧто пересчитываетсяЦена
transform, opacityтолько compositeдёшево
color, background-color, box-shadowpaintсредне
width, height, top, left, margin, paddinglayout + paintдорого

Вместо left используйте transform: translateX(), вместо width — transform: scale(). Тень дешевле анимировать через opacity псевдоэлемента с готовой тенью.

will-change: transform подсказывает браузеру вынести элемент в отдельный слой. Ставьте его точечно и только на то, что действительно анимируется: лишние слои расходуют память.

CSS: когда его хватает

.card {
  transition: transform 200ms ease, opacity 200ms ease;
}
.card:hover {
  transform: translateY(-4px);
}

@media (prefers-reduced-motion: reduce) {
  .card { transition: none; }
  .card:hover { transform: none; }
}

Для анимаций при прокрутке в современных браузерах появились scroll-driven animations (animation-timeline: view()), которые работают без JavaScript. Поддержка пока неполная, поэтому проверяйте её и делайте так, чтобы без анимации контент оставался видимым.

GSAP и Motion: анимации по прокрутке

Простое появление при прокрутке можно сделать через Intersection Observer и CSS-класс. Если нужны закрепление секции, анимация, привязанная к положению прокрутки, или сложная последовательность, удобнее библиотека.

GSAP с плагином ScrollTrigger и учётом настроек пользователя:

import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);

const mm = gsap.matchMedia();
mm.add("(prefers-reduced-motion: no-preference)", () => {
  gsap.from(".feature", {
    y: 40,
    opacity: 0,
    stagger: 0.1,
    scrollTrigger: { trigger: ".features", start: "top 80%" }
  });
});

Motion в React:

import { motion, MotionConfig } from "motion/react";

<MotionConfig reducedMotion="user">
  <motion.div
    initial={{ opacity: 0, y: 24 }}
    whileInView={{ opacity: 1, y: 0 }}
    viewport={{ once: true }}
  />
</MotionConfig>

reducedMotion="user" отключает анимацию трансформаций у тех, кто включил уменьшение движения в системе.

prefers-reduced-motion

У части людей движение на экране вызывает головокружение и тошноту. Медиазапрос prefers-reduced-motion сообщает, что пользователь попросил систему уменьшить анимации. Что делать:

  • убирать параллакс, крупные перемещения и автопрокрутку;
  • оставлять короткие изменения прозрачности и цвета — они обычно не мешают;
  • следить, чтобы контент без анимации был сразу видим, а не застревал в opacity: 0.

Как избежать рывков

  • Анимируйте transform и opacity, а не размеры и отступы.
  • Не читайте и не меняйте размеры в одном цикле (offsetHeight, затем запись стиля, затем снова чтение) — это вызывает принудительный пересчёт layout.
  • JavaScript-анимации делайте через requestAnimationFrame или библиотеку, а не через setInterval.
  • Не вешайте тяжёлую логику на событие scroll.
  • Проверяйте на слабом телефоне и в панели Performance в DevTools с замедлением CPU.
  • Не анимируйте всё подряд: одна выразительная анимация лучше десяти мелких.

Частые вопросы

Для transform и opacity разница обычно незаметна: и CSS, и хорошие библиотеки используют те же быстрые механизмы браузера. Медленными анимации делают свойства, которые вызывают layout, а не выбор технологии.

Читайте также

Есть идея или задача? Расскажите нам

Ответим в течение рабочего дня и предложим решение. Консультация бесплатная.