Why GSAP in the first place?
GSAP is the de facto choice for scroll animations because it covers everything: fade, slide, color transitions, counters, text reveals, video scrubbing. Developers install it once and use it for everything.
The cost: 40+ KB gzipped (ScrollTrigger adds ~22 KB on top of GSAP core), a non-trivial API surface, and a business license requirement for commercial SplitText usage. For most projects, 80% of that weight covers use cases you never touch.
The side-by-side
Here is the most common GSAP scroll pattern — fade + slide in on scroll:
// GSAP — 40+ KB gzipped, needs two imports
import gsap from 'gsap';
import ScrollTrigger from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
gsap.to('#hero-text', {
opacity: 1,
y: 0,
duration: 0.8,
ease: 'power2.out',
scrollTrigger: {
trigger: '#hero-text',
start: 'top 80%',
end: 'top 40%',
scrub: true,
once: true,
},
});// svg-scroll-draw v2 — ~9 KB total, one import, no plugin registration
import { scrollAnimate } from 'svg-scroll-draw';
scrollAnimate('#hero-text', {
props: {
opacity: [0, 1],
transform: ['translateY(40px)', 'translateY(0px)'],
},
trigger: { start: 'top 80%', end: 'top 40%' },
easing: 'ease-out',
once: true,
});Common patterns, migrated
Parallax background
// GSAP
gsap.to('#bg', { y: -120, ease: 'none',
scrollTrigger: { trigger: '#bg', start: 'top bottom', end: 'bottom top', scrub: true } });
// svg-scroll-draw
import { scrollParallax } from 'svg-scroll-draw';
scrollParallax('#bg', { speed: 0.4 }); // speed = fraction of element heightStats counter
// GSAP (needs a custom plugin or TextPlugin)
gsap.to({ val: 0 }, {
val: 50000, duration: 2, ease: 'power1.out',
scrollTrigger: { trigger: '#count', start: 'top 80%', once: true },
onUpdate() { document.getElementById('count').textContent = Math.round(this.targets()[0].val); },
});
// svg-scroll-draw
import { scrollCounter } from 'svg-scroll-draw';
scrollCounter('#count', { to: 50000, easing: 'ease-out', once: true });Text reveal (SplitText)
// GSAP SplitText — requires Club GreenSock ($150+/yr)
const split = new SplitText('#headline', { type: 'words' });
gsap.from(split.words, { opacity: 0, y: 24, stagger: 0.05, ease: 'power2.out',
scrollTrigger: { trigger: '#headline', start: 'top 85%', once: true } });
// svg-scroll-draw/text — free, MIT
import { scrollText } from 'svg-scroll-draw/text';
scrollText('#headline', { split: 'words', stagger: 0.05, from: { opacity: 0, y: 24 }, once: true });Video scrubbing
// GSAP
gsap.to({}, {
scrollTrigger: { trigger: '#section', start: 'top top', end: 'bottom top', scrub: true,
onUpdate: self => { video.currentTime = self.progress * video.duration; } },
});
// svg-scroll-draw/video
import { scrollVideo } from 'svg-scroll-draw/video';
scrollVideo('#hero-video', { trigger: { start: 'top top', end: 'bottom top' } });The instance API is the same
Every function in svg-scroll-draw returns the same instance object, so programmatic control feels identical to GSAP:
const anim = scrollAnimate('#el', { props: { opacity: [0, 1] } });
anim.pause(); // pause at current frame
anim.resume(); // resume
anim.seek(0.5); // jump to 50%
anim.replay(); // reset and replay
anim.getProgress(); // → 0–1
anim.destroy(); // remove all listenersWhen to still use GSAP
svg-scroll-draw covers the 95% case. There are scenarios where GSAP is still the right tool:
- Complex multi-element non-scroll timelines (absolute time, tweening unrelated to scroll)
- Physics simulations and draggable interactions (Draggable plugin)
- Advanced SVG morphing with incompatible path structures (MorphSVG plugin)
- Canvas / WebGL animations
For everything scroll-driven — and that is the vast majority of landing page and marketing site animation — svg-scroll-draw v2 gets you there at a fraction of the bundle cost.
Further reading