Animate multiple elements
on scroll — one call.
Every real landing page needs more than one animated element. svg-scroll-draw ships four group APIs for fan-out, cascade, and parallax — all in svg-scroll-draw/group.
1. The problem with animating many elements
When you have a feature grid, testimonials row, or pricing table, you end up writing the same scrollAnimate call for every element:
// Before group APIs — repetitive and brittle
scrollAnimate(card1, { props: { opacity: [0, 1] }, easing: 'ease-out', once: true });
scrollAnimate(card2, { props: { opacity: [0, 1] }, easing: 'ease-out', once: true });
scrollAnimate(card3, { props: { opacity: [0, 1] }, easing: 'ease-out', once: true });
// And you have to track all three instances for cleanup:
// inst1.destroy(); inst2.destroy(); inst3.destroy();The group APIs collapse this to one call that returns a single combined instance — destroy() cleans up everything at once.
2. scrollAnimateGroup — fan-out simultaneously
All elements animate at the same time as the section scrolls into view. Each tracks its own scroll position independently, so elements higher on the page reveal slightly before lower ones — natural cascade for free.
import { scrollAnimateGroup } from 'svg-scroll-draw/group';
// All cards animate simultaneously — same options, one call
const group = scrollAnimateGroup(
document.querySelectorAll('.feature-card'),
{
props: {
opacity: [0, 1],
transform: ['translateY(40px)', 'translateY(0)'],
},
easing: 'ease-out',
once: true,
}
);
// Full instance API on the whole group
group.replay(); // replay all
group.pause(); // pause all
group.destroy(); // cleanup on unmountReact
import { useEffect, useRef } from 'react';
import { scrollAnimateGroup } from 'svg-scroll-draw/group';
export function FeatureGrid({ features }) {
const containerRef = useRef(null);
useEffect(() => {
if (!containerRef.current) return;
const cards = containerRef.current.querySelectorAll('.card');
const group = scrollAnimateGroup(Array.from(cards), {
props: { opacity: [0, 1], transform: ['translateY(32px)', 'translateY(0)'] },
easing: 'ease-out',
once: true,
});
return () => group.destroy();
}, []);
return (
<div ref={containerRef} className="grid grid-cols-3 gap-6">
{features.map(f => (
<div key={f.id} className="card p-6 rounded-2xl border">
<h3>{f.title}</h3>
<p>{f.description}</p>
</div>
))}
</div>
);
}3. scrollAnimateSequence — cascade one by one
Each element starts only after the previous one reaches 100%. Perfect for step-by-step reveals, numbered lists, or onboarding flows.
import { scrollAnimateSequence } from 'svg-scroll-draw/group';
// Step 1 animates fully, then step 2 starts, then step 3
scrollAnimateSequence(
document.querySelectorAll('.onboarding-step'),
{
props: {
opacity: [0, 1],
transform: ['translateX(-24px)', 'translateX(0)'],
},
easing: 'ease-out',
onComplete: () => console.log('a step finished'),
}
);Internally each step is forced to once: trueso completing a step and scrolling back doesn't reset it and break the chain.
4. scrollParallaxGroup — multi-layer parallax
Apply the same parallax speed to multiple elements at once. Typical use: floating UI badges, background texture elements, or decorative shapes that all move at the same rate.
import { scrollParallaxGroup } from 'svg-scroll-draw/group';
// All three decorative shapes float upward at 30% of scroll speed
scrollParallaxGroup(
['#circle-1', '#circle-2', '#dot-cluster'],
{ speed: 0.3 }
);
// Background layer drifts opposite direction
scrollParallaxGroup(
['#bg-gradient', '#noise-overlay'],
{ speed: -0.15 }
);Multi-layer depth effect
Call scrollParallaxGroup multiple times with different speeds for a classic depth illusion:
import { scrollParallaxGroup } from 'svg-scroll-draw/group';
// Far background — moves slowest
scrollParallaxGroup(['.layer-far'], { speed: 0.1 });
// Mid layer
scrollParallaxGroup(['.layer-mid'], { speed: 0.25 });
// Near foreground — moves fastest
scrollParallaxGroup(['.layer-near'], { speed: 0.5 });
// Floating UI elements — drift opposite direction
scrollParallaxGroup(['.badge', '.tag', '.pill'], { speed: -0.2 });5. scrollDrawGroup — SVG paths in sync
The original group API — animate multiple SVG containers simultaneously with scrollDraw. Same pattern: one call, combined instance.
import { scrollDrawGroup, scrollDrawSequence } from 'svg-scroll-draw/group';
// Three SVG icons draw at the same time
const group = scrollDrawGroup(
['#icon-speed', '#icon-size', '#icon-framework'],
{ easing: 'ease-out', fade: true, once: true }
);
// Or draw them in sequence (speed → size → framework)
const seq = scrollDrawSequence(
['#icon-speed', '#icon-size', '#icon-framework'],
{ easing: 'spring', fade: true }
);6. Real-world patterns
Pricing section — staggered cards + counters
import { scrollAnimateGroup } from 'svg-scroll-draw/group';
import { scrollCounter } from 'svg-scroll-draw';
// Pricing cards fan in
scrollAnimateGroup(document.querySelectorAll('.pricing-card'), {
props: { opacity: [0, 1], transform: ['translateY(32px)', 'translateY(0)'] },
easing: 'ease-out',
once: true,
});
// Price numbers count up independently
document.querySelectorAll('.price-number').forEach((el, i) => {
const prices = [9, 29, 79];
scrollCounter(el, {
to: prices[i],
format: n => '$' + Math.round(n),
easing: 'ease-out',
once: true,
trigger: { start: `top ${85 - i * 5}%`, end: `top ${50 - i * 5}%` },
});
});Hero with parallax depth + text reveal
import { scrollParallaxGroup } from 'svg-scroll-draw/group';
import { scrollText } from 'svg-scroll-draw/text';
// Background layers drift at different depths
scrollParallaxGroup(['.bg-blur', '.bg-gradient'], { speed: 0.12 });
scrollParallaxGroup(['.hero-badge', '.hero-dot'], { speed: -0.18 });
// Headline reveals word by word on top
scrollText('#hero-headline', {
split: 'words',
stagger: 0.06,
from: { opacity: 0, y: 32 },
once: true,
});Feature list — sequential entrance
import { scrollAnimateSequence } from 'svg-scroll-draw/group';
// Each feature row slides in after the previous one
scrollAnimateSequence(
document.querySelectorAll('.feature-row'),
{
props: {
opacity: [0, 1],
transform: ['translateX(-20px)', 'translateX(0)'],
},
easing: 'ease-out',
}
);7. API summary
| Function | Behaviour | Options type |
|---|---|---|
| scrollAnimateGroup | All elements animate simultaneously | ScrollAnimateOptions |
| scrollAnimateSequence | Each starts only after the previous completes | ScrollAnimateOptions |
| scrollParallaxGroup | All elements parallax at the same speed | ScrollParallaxOptions |
| scrollDrawGroup | All SVG containers draw simultaneously | ScrollDrawOptions |
| scrollDrawSequence | SVG containers draw in strict sequence | ScrollDrawOptions |
All functions return a combined ScrollDrawInstance with destroy, replay, pause, resume, seek, and getProgress. All are available in svg-scroll-draw/group.