Scroll-Driven UI Without Jank
Lenis, GSAP ScrollTrigger, and the discipline of animating only transform and opacity.

Scroll animations go wrong when they fight the browser. Layout thrashing, scroll jank, and main-thread clustering all come from the same mistake: animating properties that trigger reflow.
Lenis owns scroll; GSAP owns time
Lenis smooths wheel input into native scroll. GSAP reads that scroll via ScrollTrigger and drives transforms. The two systems stay in sync through a single ticker instead of competing proxies.
- Animate transform and opacity only
- matchMedia for reduced-motion fallbacks
- Section ids that match navigation and progress rails
- Kill timelines on unmount to prevent memory leaks
Motion should explain structure, not decorate it.