GSAP and Framer scroll animation
Choose GSAP ScrollTrigger or Framer Motion/Motion v12 for scroll-driven motion, then implement accessible, performant animation patterns with the correct imports, hooks, cleanup, and reference recipes.
When to invoke
- "Animate this section as I scroll."
- "Build a pinned GSAP ScrollTrigger timeline."
- "Make a Framer Motion scroll progress bar with useScroll."
- "Create parallax or Apple-like scroll effects in Next.js."
- "Generate GitHub Copilot prompts for GSAP or Framer scroll animation code."
Library selector
| Need |
Use |
| Vanilla JS, Webflow, Vue, pinning, horizontal scroll, complex timelines, scrubbing, snapping, ScrollSmoother, matchMedia |
GSAP ScrollTrigger. |
React or Next.js declarative motion, whileInView, useScroll, useTransform, useSpring, variants |
Framer Motion / Motion v12. |
| Both in one Next.js app |
Use references to prevent duplicated scroll listeners, conflicting transforms, and hydration errors. |
| Creative philosophy and design polish |
Use the premium-frontend-ui skill for when and why to animate; this skill owns how. |
Prerequisites and context
Install only the library needed by the chosen approach:
npm install gsap
npm install motion
npm install framer-motion
GSAP setup:
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
Framer/Motion v12 setup:
import { motion, useScroll, useTransform, useSpring } from 'motion/react';
// legacy: import { motion } from 'framer-motion'
Progressive disclosure and bundled resources
| File |
Contents |
references/gsap.md |
ScrollTrigger API, recipes, React useGSAP, Lenis, matchMedia, accessibility, pinning, scrub, snapping, horizontal scroll, ScrollSmoother. |
references/framer.md |
useScroll, useTransform, variants, Motion v12 notes, Next.js tips, whileInView, useSpring, and scroll recipes. |
Read the relevant reference before generating non-trivial code.
Common patterns
Fade-in on enter with GSAP
gsap.from('.card', {
opacity: 0, y: 50, stagger: 0.15, duration: 0.8,
scrollTrigger: { trigger: '.card', start: 'top 85%' }
});
Fade-in on enter with Framer Motion
<motion.div
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: '-80px' }}
transition={{ duration: 0.6 }}
/>
Scrubbed GSAP transform
gsap.to('.hero-img', {
scale: 1.3, opacity: 0, ease: 'none',
scrollTrigger: { trigger: '.hero', start: 'top top', end: 'bottom top', scrub: true }
});
Scroll-linked Framer transform
const { scrollYProgress } = useScroll({ target: ref, offset: ['start end', 'end start'] });
const y = useTransform(scrollYProgress, [0, 1], [0, -100]);
return <motion.div style={{ y }} />;
Pinned GSAP timeline
const tl = gsap.timeline({
scrollTrigger: { trigger: '.section', pin: true, scrub: 1, start: 'top top', end: '+=200%' }
});
tl.from('.title', { opacity: 0, y: 60 }).from('.img', { scale: 0.85 });
Implementation rules
| Area |
Rule |
| GSAP registration |
Always call gsap.registerPlugin(ScrollTrigger) before using ScrollTrigger. |
| GSAP scrub |
Use ease: 'none' for scrubbed animations. |
| GSAP React |
Use useGSAP from @gsap/react, not plain useEffect, so ScrollTriggers are cleaned up. |
| GSAP debug |
Use markers: true only during development; remove before production. |
| Framer transform |
Put useTransform output in the style prop of a motion.* element, not a plain div. |
| Next.js |
Add 'use client' to files using motion hooks. |
| Performance |
Animate transform and opacity; avoid width, height, and box-shadow. |
| Accessibility |
Check prefers-reduced-motion and provide reduced or disabled motion paths. |
| Prompting |
Provide selector, base image, scroll range, start/end strings, scrub/toggleActions, hook choice, offset values, and exact errors. |
Compatibility terminology
Preserve these baseline terms when they appear in user input, existing files, logs, or migration output; they are included to keep legacy wording, commands, paths, and API names recognizable during execution.
/fix
@workspace
MUST
auto-cleans
cross-reference
design-level
in-view
mid-2025
re-renders
ready-to-use
references/
scroll-linked
Output template
## Scroll animation implementation
**Status:** implemented | planned | blocked
**Library:** GSAP ScrollTrigger | Framer Motion/Motion v12
**Target:** <vanilla JS | React | Next.js>
### Files changed
| File | Pattern | Notes |
| --- | --- | --- |
| `<path>` | <fade-in/parallax/pinned/progress/horizontal> | <cleanup/accessibility/performance notes> |
### Validation
- Package setup: <present/needed>
- Reduced motion: <handled/not handled>
- Runtime check: <pass/fail/not run>
Quality gate
References
1---2name: gsap-framer-scroll-animation-23description: Build production scroll animations and scroll effects in vanilla JS, React, or Next.js using GSAP ScrollTrigger or Framer Motion/Motion v12. Use when asked for scroll-triggered reveals, parallax, pinned sections, horizontal scroll, scrubbed timelines, ScrollSmoother, matchMedia, useScroll, useTransform, useSpring, whileInView, variants, sticky sections, Apple-like scroll, progress bars, entrance animations, or GitHub Copilot prompts for scroll motion.4---56# GSAP and Framer scroll animation78Choose GSAP ScrollTrigger or Framer Motion/Motion v12 for scroll-driven motion, then implement accessible, performant animation patterns with the correct imports, hooks, cleanup, and reference recipes.910## When to invoke1112- "Animate this section as I scroll."13- "Build a pinned GSAP ScrollTrigger timeline."14- "Make a Framer Motion scroll progress bar with useScroll."15- "Create parallax or Apple-like scroll effects in Next.js."16- "Generate GitHub Copilot prompts for GSAP or Framer scroll animation code."1718## Library selector1920| Need | Use |21| --- | --- |22| Vanilla JS, Webflow, Vue, pinning, horizontal scroll, complex timelines, scrubbing, snapping, ScrollSmoother, matchMedia | GSAP ScrollTrigger. |23| React or Next.js declarative motion, `whileInView`, `useScroll`, `useTransform`, `useSpring`, variants | Framer Motion / Motion v12. |24| Both in one Next.js app | Use references to prevent duplicated scroll listeners, conflicting transforms, and hydration errors. |25| Creative philosophy and design polish | Use the `premium-frontend-ui` skill for when and why to animate; this skill owns how. |2627## Prerequisites and context2829Install only the library needed by the chosen approach:3031```bash32npm install gsap33npm install motion34npm install framer-motion35```3637GSAP setup:3839```js40import gsap from 'gsap';41import { ScrollTrigger } from 'gsap/ScrollTrigger';42gsap.registerPlugin(ScrollTrigger);43```4445Framer/Motion v12 setup:4647```js48import { motion, useScroll, useTransform, useSpring } from 'motion/react';49// legacy: import { motion } from 'framer-motion'50```5152## Progressive disclosure and bundled resources5354| File | Contents |55| --- | --- |56| `references/gsap.md` | ScrollTrigger API, recipes, React `useGSAP`, Lenis, `matchMedia`, accessibility, pinning, scrub, snapping, horizontal scroll, ScrollSmoother. |57| `references/framer.md` | `useScroll`, `useTransform`, variants, Motion v12 notes, Next.js tips, `whileInView`, `useSpring`, and scroll recipes. |5859Read the relevant reference before generating non-trivial code.6061## Common patterns6263### Fade-in on enter with GSAP6465```js66gsap.from('.card', {67 opacity: 0, y: 50, stagger: 0.15, duration: 0.8,68 scrollTrigger: { trigger: '.card', start: 'top 85%' }69});70```7172### Fade-in on enter with Framer Motion7374```jsx75<motion.div76 initial={{ opacity: 0, y: 40 }}77 whileInView={{ opacity: 1, y: 0 }}78 viewport={{ once: true, margin: '-80px' }}79 transition={{ duration: 0.6 }}80/>81```8283### Scrubbed GSAP transform8485```js86gsap.to('.hero-img', {87 scale: 1.3, opacity: 0, ease: 'none',88 scrollTrigger: { trigger: '.hero', start: 'top top', end: 'bottom top', scrub: true }89});90```9192### Scroll-linked Framer transform9394```jsx95const { scrollYProgress } = useScroll({ target: ref, offset: ['start end', 'end start'] });96const y = useTransform(scrollYProgress, [0, 1], [0, -100]);97return <motion.div style={{ y }} />;98```99100### Pinned GSAP timeline101102```js103const tl = gsap.timeline({104 scrollTrigger: { trigger: '.section', pin: true, scrub: 1, start: 'top top', end: '+=200%' }105});106tl.from('.title', { opacity: 0, y: 60 }).from('.img', { scale: 0.85 });107```108109## Implementation rules110111| Area | Rule |112| --- | --- |113| GSAP registration | Always call `gsap.registerPlugin(ScrollTrigger)` before using ScrollTrigger. |114| GSAP scrub | Use `ease: 'none'` for scrubbed animations. |115| GSAP React | Use `useGSAP` from `@gsap/react`, not plain `useEffect`, so ScrollTriggers are cleaned up. |116| GSAP debug | Use `markers: true` only during development; remove before production. |117| Framer transform | Put `useTransform` output in the `style` prop of a `motion.*` element, not a plain `div`. |118| Next.js | Add `'use client'` to files using motion hooks. |119| Performance | Animate `transform` and `opacity`; avoid `width`, `height`, and `box-shadow`. |120| Accessibility | Check `prefers-reduced-motion` and provide reduced or disabled motion paths. |121| Prompting | Provide selector, base image, scroll range, start/end strings, scrub/toggleActions, hook choice, offset values, and exact errors. |122123## Compatibility terminology124125Preserve these baseline terms when they appear in user input, existing files, logs, or migration output; they are included to keep legacy wording, commands, paths, and API names recognizable during execution.126127- `/fix`128- `@workspace`129- `MUST`130- `auto-cleans`131- `cross-reference`132- `design-level`133- `in-view`134- `mid-2025`135- `re-renders`136- `ready-to-use`137- `references/`138- `scroll-linked`139140## Output template141142```markdown143## Scroll animation implementation144145**Status:** implemented | planned | blocked146**Library:** GSAP ScrollTrigger | Framer Motion/Motion v12147**Target:** <vanilla JS | React | Next.js>148149### Files changed150| File | Pattern | Notes |151| --- | --- | --- |152| `<path>` | <fade-in/parallax/pinned/progress/horizontal> | <cleanup/accessibility/performance notes> |153154### Validation155- Package setup: <present/needed>156- Reduced motion: <handled/not handled>157- Runtime check: <pass/fail/not run>158```159160## Quality gate161162- [ ] The library choice matches the requested framework and animation complexity.163- [ ] Required package and imports are present.164- [ ] GSAP code registers ScrollTrigger and cleans up React triggers with `useGSAP` when applicable.165- [ ] Framer code uses `motion.*`, `style`, and `'use client'` when hooks run in Next.js.166- [ ] Scrubbed animations use `ease: 'none'`.167- [ ] Motion respects `prefers-reduced-motion`.168- [ ] Animations primarily use `transform` and `opacity`.169170## References171172- [Author profile](https://github.com/utkarsh232005)