Lightweight scroll-driven animations using native CSS Scroll Timeline API. Zero dependencies. Pure performance.
Most animation libraries are bloated with features you don't need. GSAP, Framer Motion, and others add significant bundle size and complexity. This toolkit uses native browser APIs for smooth, performant animations with zero dependencies.
npm install react-scroll-motionimport { RevealOnScroll, ScrollProgress } from 'react-scroll-motion';
export default function Page() {
return (
<>
<ScrollProgress color="#6366f1" height={3} />
<RevealOnScroll animation="fadeInUp" delay={200}>
<h1>Hello World</h1>
</RevealOnScroll>
</>
);
}Wraps any element and animates it when scrolled into view.
<RevealOnScroll
animation="fadeInUp"
delay={200}
duration={600}
threshold={0.1}
once={true}
easing="ease-out"
className="my-class"
>
<Card />
</RevealOnScroll>Props:
animation:'fadeIn' | 'fadeInUp' | 'fadeInDown' | 'slideInLeft' | 'slideInRight' | 'scaleUp' | 'scaleDown' | 'rotateIn' | 'blurIn'delay?:number- Delay in ms before animation starts (default:0)duration?:number- Animation duration in ms (default:600)threshold?:number- Intersection threshold 0-1 (default:0.1)once?:boolean- Animate only once (default:true)easing?:string- CSS easing function (default:'ease-out')className?:string- Additional CSS classes
Fixed progress bar at the top of the page showing scroll progress.
<ScrollProgress
color="#6366f1"
height={3}
zIndex={9999}
/>Props:
color?:string- Progress bar color (default:'#6366f1')height?:number- Bar height in pixels (default:3)zIndex?:number- CSS z-index (default:9999)
Section where content moves slower than scroll speed for parallax effect.
<ParallaxSection speed={0.5} className="py-32">
<HeroContent />
</ParallaxSection>Props:
speed?:number- Parallax speed multiplier 0-1 (default:0.5)children:React.ReactNode- Content to parallaxclassName?:string- Additional CSS classes
Number that counts up when scrolled into view.
<CountOnScroll
from={0}
to={10000}
duration={2000}
formatFn={(n) => `$${n.toLocaleString()}`}
className="text-4xl font-bold"
/>Props:
from:number- Starting numberto:number- Ending numberduration?:number- Count duration in ms (default:2000)formatFn?:(value: number) => string- Format function (default:toLocaleString())className?:string- Additional CSS classes
Animates children one by one with stagger delay.
<StaggerChildren
animation="fadeInUp"
staggerDelay={100}
className="grid grid-cols-3 gap-4"
>
<Card />
<Card />
<Card />
</StaggerChildren>Props:
animation: Animation type (same asRevealOnScroll)staggerDelay?:number- Delay between children in ms (default:100)duration?:number- Animation duration in msthreshold?:number- Intersection threshold 0-1once?:boolean- Animate only onceeasing?:string- CSS easing functionclassName?:string- Additional CSS classes
Low-level hook for custom animations.
import { useScrollAnimation } from 'react-scroll-motion';
function MyComponent() {
const { ref, isVisible, progress } = useScrollAnimation('fadeIn', {
delay: 200,
duration: 600,
threshold: 0.1,
once: true,
easing: 'ease-out',
});
return (
<div ref={ref}>
Visible: {isVisible ? 'Yes' : 'No'}
Progress: {Math.round(progress * 100)}%
</div>
);
}Returns:
ref:React.RefObject<HTMLElement>- Attach to elementisVisible:boolean- Whether element is in viewportprogress:number- Scroll progress 0-1
| Type | Description |
|---|---|
fadeIn |
Fade in opacity |
fadeInUp |
Fade in + slide up |
fadeInDown |
Fade in + slide down |
slideInLeft |
Slide in from left |
slideInRight |
Slide in from right |
scaleUp |
Scale up from 0.8 |
scaleDown |
Scale down from 1.2 |
rotateIn |
Rotate + scale in |
blurIn |
Blur to clear |
All components and hooks are fully typed with strict TypeScript.
import type { AnimationType, ScrollAnimationOptions } from 'react-scroll-motion';
const animation: AnimationType = 'fadeInUp';
const options: ScrollAnimationOptions = {
delay: 200,
duration: 600,
threshold: 0.1,
once: true,
easing: 'ease-out',
};This library uses native CSS Scroll Timeline API and IntersectionObserver:
- ✅ Chrome 115+
- ✅ Edge 115+
- ✅ Safari 17.5+ (with polyfill)
- ✅ Firefox (with polyfill)
For older browsers, animations gracefully degrade to instant visibility. Consider using the scroll-timeline polyfill for broader support.
- Zero dependencies
- < 3KB gzipped
- Native browser APIs
- Hardware-accelerated transforms
- Passive scroll listeners
- Automatic cleanup on unmount
View the live demo on Vercel →
MIT