GSAP Basics with Claude Code

Lesson 12

GSAP is one of the most expressive animation libraries for the web. With Claude Code, you can describe exactly what you want to animate and get working GSAP code without memorizing its API.

Starting simple

페이지 로드 시 다음 순서로 나타나는 애니메이션을 GSAP로 만들어줘:
1. nav가 위에서 내려오며 fade in (y: -20 → 0, opacity 0→1, 0.4s)
2. 히어로 제목이 약간 아래에서 올라오며 나타남 (y: 24 → 0, 0.5s, delay 0.2s)
3. 서브텍스트 (0.4s, delay 0.4s)
4. CTA 버튼들 (stagger 0.1s, delay 0.6s)
ease는 모두 power2.out

Reading the output

Claude Code will produce something like:

gsap.registerPlugin();

const tl = gsap.timeline({ defaults: { ease: 'power2.out' } });

tl.from('nav', { y: -20, opacity: 0, duration: 0.4 })
  .from('h1', { y: 24, opacity: 0, duration: 0.5 }, '-=0.2')
  .from('.hero-sub', { opacity: 0, duration: 0.4 }, '-=0.2')
  .from('.btn', { opacity: 0, y: 10, duration: 0.3, stagger: 0.1 }, '-=0.1');

Key patterns to understand:

  • gsap.timeline() chains animations sequentially
  • '-=0.2' means “start 0.2s before the previous animation ends”
  • stagger applies the same animation to multiple elements with a time offset between each

Asking for explanations

When Claude Code produces code you don’t understand, ask:

이 코드에서 '-=0.2' 는 어떤 의미야?
gsap.timeline과 gsap.to의 차이는?

Claude Code explains its own output. This is how you learn — not by studying documentation, but by asking about real code you’re already using.

The demo

The demo is a landing page hero section with the full sequence: nav → heading → subtext → buttons → image. Each element is timed and eased through a GSAP timeline. Read script.js to see the complete code.

Source Code script.js
gsap.registerPlugin(ScrollTrigger);

// ── Page entrance timeline ────────────────────────────────
const tl = gsap.timeline({ defaults: { ease: 'power3.out' } });

// 1. Nav slides down
tl.from('#siteNav', { y: -20, opacity: 0, duration: 0.4 })

// 2. Hero label
  .from('.hero-label', { opacity: 0, duration: 0.3 }, '-=0.1')

// 3. Title lines staggered
  .from('.hero-title span', { y: 40, opacity: 0, duration: 0.6, stagger: 0.1 }, '-=0.1')

// 4. Sub + actions
  .from('.hero-sub', { y: 16, opacity: 0, duration: 0.45 }, '-=0.3')
  .from('.hero-actions > *', { y: 10, opacity: 0, stagger: 0.08, duration: 0.35 }, '-=0.2');

// ── Concept cards: scroll-triggered stagger ───────────────
gsap.from('.concept-card', {
  scrollTrigger: {
    trigger: '.concept-grid',
    start: 'top 80%',
  },
  y: 24,
  opacity: 0,
  duration: 0.5,
  stagger: 0.08,
  ease: 'power2.out',
});

// ── Code block: scroll-triggered fade ────────────────────
gsap.from('.code-block', {
  scrollTrigger: {
    trigger: '.code-block',
    start: 'top 85%',
  },
  y: 16,
  opacity: 0,
  duration: 0.5,
  ease: 'power2.out',
});

gsap.from('.code-note', {
  scrollTrigger: {
    trigger: '.code-note',
    start: 'top 90%',
  },
  opacity: 0,
  duration: 0.4,
  delay: 0.2,
  ease: 'power2.out',
});