pimenov.ai

База знаний

GSAP — библиотека анимации для веба

GSAP (GreenSock) — JavaScript-библиотека анимации для веба: твины, таймлайны, ScrollTrigger, интеграция с React и сборка анимированных лендингов в Codex Sites.

Опубликовано

GSAP (GreenSock Animation Platform) — JavaScript-библиотека для анимации всего, до чего дотягивается код: CSS, SVG, canvas, WebGL и обычные объекты. С 30 апреля 2025 года доступна бесплатно вместе со всеми плагинами благодаря поддержке Webflow.

Что такое GSAP

GSAP — движок анимации, который работает поверх любого фреймворка и в любом современном браузере. Вместо ручной возни с CSS-переходами и requestAnimationFrame вы описываете анимацию декларативно, а библиотека берёт на себя тайминги, сглаживание и производительность.

Три причины, по которым GSAP держит первое место в вебе больше 15 лет:

  • Стабильная работа во всех браузерах, включая пограничные случаи с SVG и трансформациями.
  • Точный контроль над последовательностями через таймлайны.
  • Экосистема плагинов: скролл, морфинг, разбивка текста, перетаскивание.

Раньше часть плагинов пряталась за платной Club-подпиской. Теперь весь набор открыт и разрешён в коммерческих проектах.

Ключевые возможности

ВозможностьЧто делает
gsap.to() / from() / fromTo()Базовые твины: анимируют свойства от одного значения к другому
TimelineСобирает анимации в управляемую последовательность с паузами и наложением
EasingНастраивает характер движения: пружина, отскок, плавное торможение
staggerЗапускает анимацию по очереди для списка элементов
gsap.matchMedia()Разные анимации под брейкпоинты и prefers-reduced-motion
ScrollTriggerПривязывает анимацию к скроллу: reveal, pin, parallax, scrub
SplitTextРазбивает текст на строки, слова и буквы для анимации
FlipПлавно анимирует переход между двумя состояниями макета
DraggableПеретаскивание, инерция, привязка к сетке

Установка и подключение

Быстрый старт через CDN

<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
<script>
  gsap.to(".box", { x: 300, duration: 1, ease: "power2.out" });
</script>

Установка через npm

npm install gsap
import gsap from "gsap"

gsap.to(".box", { rotation: 360, duration: 2 })

Регистрация плагинов

Плагины подключаются отдельно и регистрируются один раз при старте приложения:

import gsap from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"

gsap.registerPlugin(ScrollTrigger)
💡
Если анимация плагина молча не работает, первым делом проверьте, вызвали ли вы gsap.registerPlugin(). Это самая частая причина.

Интеграция с React

В React анимации нужно запускать после монтирования и убирать при размонтировании. Для этого у GSAP есть официальный пакет @gsap/react с хуком useGSAP().

npm install gsap @gsap/react

Хук useGSAP

useGSAP() работает похоже на useEffect, но сам собирает все созданные анимации и очищает их, когда компонент исчезает. Ручной cleanup писать не нужно.

import { useRef } from "react"
import gsap from "gsap"
import { useGSAP } from "@gsap/react"

gsap.registerPlugin(useGSAP)

function Hero() {
  const container = useRef()

  useGSAP(
    () => {
      gsap.from(".title", { y: 40, opacity: 0, duration: 0.8, ease: "power2.out" })
      gsap.from(".subtitle", { y: 20, opacity: 0, duration: 0.6, delay: 0.2 })
    },
    { scope: container }
  )

  return (
    <section ref={container}>
      <h1 className="title">Заголовок</h1>
      <p className="subtitle">Подзаголовок</p>
    </section>
  )
}

Зачем нужен scope

Параметр scope ограничивает селекторы (.title, .subtitle) пределами контейнера. Так анимация одного компонента не заденет одноимённые классы в другой части страницы.

ScrollTrigger внутри компонента

import { useRef } from "react"
import gsap from "gsap"
import { ScrollTrigger } from "gsap/ScrollTrigger"
import { useGSAP } from "@gsap/react"

gsap.registerPlugin(ScrollTrigger, useGSAP)

function Features() {
  const container = useRef()

  useGSAP(
    () => {
      gsap.from(".card", {
        y: 60,
        opacity: 0,
        stagger: 0.15,
        scrollTrigger: { trigger: ".cards", start: "top 80%" },
      })
    },
    { scope: container }
  )

  return (
    <div ref={container}>
      <div className="cards">
        <div className="card">1</div>
        <div className="card">2</div>
        <div className="card">3</div>
      </div>
    </div>
  )
}
⚠️
В Next.js и других SSR-фреймворках держите импорт ScrollTrigger и запуск анимаций в клиентском компоненте. useGSAP выполняется после монтирования, поэтому обращения к DOM внутри него безопасны.

Тарифы и лицензия

С 30 апреля 2025 года GSAP бесплатен для всех, включая весь набор ранее платных плагинов и коммерческое использование. Отдельная подписка больше не нужна.

⚖️
Одно ограничение в лицензии сохранилось: GSAP нельзя встраивать в продукты, которые конкурируют с визуальным конструктором Webflow, то есть в собственные no-code аниматоры. Для обычных сайтов, лендингов и приложений ограничений нет.

Практические сценарии

Появление блоков по мере скролла

gsap.from(".section", {
  y: 50,
  opacity: 0,
  duration: 0.8,
  scrollTrigger: { trigger: ".section", start: "top 85%" },
})

Закрепление секции и параллакс

gsap.to(".bg", {
  yPercent: -30,
  ease: "none",
  scrollTrigger: {
    trigger: ".hero",
    start: "top top",
    end: "bottom top",
    scrub: true,
    pin: true,
  },
})

Анимация заголовка по буквам

import { SplitText } from "gsap/SplitText"
gsap.registerPlugin(SplitText)

const split = new SplitText(".headline", { type: "chars" })
gsap.from(split.chars, { y: 20, opacity: 0, stagger: 0.03 })

Микровзаимодействия на кнопках

const btn = document.querySelector(".cta")
btn.addEventListener("mouseenter", () => gsap.to(btn, { scale: 1.05, duration: 0.2 }))
btn.addEventListener("mouseleave", () => gsap.to(btn, { scale: 1, duration: 0.2 }))

Использование в Codex Sites при сборке лендингов

Codex Sites — это плагин Codex (@Sites), который по вашему описанию собирает, сохраняет и деплоит сайты, веб-приложения и дашборды на инфраструктуре OpenAI. Для лендинга это удобно: вы описываете структуру и анимации словами, а агент собирает и публикует готовую страницу. GSAP хорошо вписывается в такой процесс — как правило, библиотеку можно подключить одним тегом в <head>, после чего агент расставляет анимации по разметке.

ℹ️
Codex Sites появился в превью в июне 2026 (сначала для планов Business и Enterprise), а с 9 июля 2026 стал доступен платным подписчикам уже с публично доступными сайтами. Хостинг обеспечивает OpenAI, поэтому публичная доступность лендинга наружу зависит от вашего плана.

Практический порядок:

  1. В промпте попросите подключить GSAP и нужные плагины через CDN.
  2. Опишите анимации по секциям конкретно: что двигается, откуда, с какой задержкой.
  3. Попросите обернуть запуск в проверку prefers-reduced-motion, чтобы уважать настройки доступности.
  4. После сборки проверьте страницу на мобильных: тяжёлые pin и scrub иногда стоит отключать на узких экранах через gsap.matchMedia().

Пример части промпта для Codex:

Подключи GSAP и ScrollTrigger через CDN. Сделай на лендинге:
- герой: заголовок и кнопка появляются снизу с задержкой 0.2с;
- блок преимуществ: карточки выезжают по очереди при попадании в 80% экрана;
- фоновая картинка героя двигается параллаксом при скролле.
Оберни анимации в matchMedia: на экранах уже 640px параллакс отключи.

Такой подход даёт живой лендинг без ручной вёрстки анимаций: вы формулируете поведение словами, а агент собирает готовую страницу.

Частые ошибки: что делать, если…

  • Анимация плагина не срабатывает — не вызван gsap.registerPlugin().
  • Анимация дёргается — вы анимируете top / left вместо x / y; трансформации работают на GPU и идут плавнее.
  • В React анимация повторяется или ломается при переходах — запуск не обёрнут в useGSAP() либо не задан scope.
  • ScrollTrigger считает позиции неверно — после загрузки шрифтов и картинок вызовите ScrollTrigger.refresh().
  • Анимация мешает пользователям — не обработан prefers-reduced-motion через gsap.matchMedia().

Ссылки

По теме

GSAP хорошо ложится на лендинги, которые вы собираете с ИИ-агентами: пара точных анимаций оживляет страницу и помогает вести внимание к главному.

Если захотите обсудить, как это применить у себя или в команде — пишите в Telegram @pimenov