How to Sync SVG Animations with Page Scroll
Data storytelling platforms use scroll-synchronized SVG
animations—often called “scrollytelling”—to guide readers through
complex datasets by tying visual state changes directly to the user’s
scroll progress. By mapping viewport coordinates to animation timelines
using browser APIs, CSS tricks like stroke-dashoffset, and
JavaScript libraries, developers transform static vector graphics into
responsive, interactive visual narratives.
1. Mapping Scroll Progress to Animation Timelines
The fundamental mechanism behind scroll-driven animation is
normalizing scroll distance into a progress value between 0
and 1 (or 0% to 100%).
Platforms define a “trigger container” (often a tall, invisible
<div> with styling like height: 300vh)
and stick the SVG element in place using CSS
position: sticky; top: 0;. As the user scrolls through the
container:
- Start Point: The top of the container enters the viewport.
- Current Progress: Calculated as
progress = (currentScroll - startScroll) / totalScrollDistance. - End Point: The bottom of the container leaves the viewport, completing the animation timeline.
2. SVG Line Drawing
with stroke-dashoffset
One of the most common data storytelling techniques is revealing line charts, trend lines, or network paths as the user scrolls. This is achieved via SVG stroke properties:
path.getTotalLength(): JavaScript measures the exact length of an SVG<path>.stroke-dasharray: Set to the path’s total length, creating a dash pattern as long as the entire line.stroke-dashoffset: Initially set to the total length (hiding the stroke completely), then dynamically reduced to0proportional to the scroll progress, creating the illusion of the line being drawn in real time.
const path = document.querySelector('path');
const length = path.getTotalLength();
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
window.addEventListener('scroll', () => {
const scrollPercent = (document.documentElement.scrollTop + document.body.scrollTop) /
(document.documentElement.scrollHeight - document.documentElement.clientHeight);
const drawLength = length * scrollPercent;
path.style.strokeDashoffset = length - drawLength;
});3. Native CSS Scroll-Driven Animations
Modern browsers support CSS Scroll-Driven Animations, eliminating the need for JavaScript scroll event listeners:
@keyframes drawChart {
from { stroke-dashoffset: 1000; }
to { stroke-dashoffset: 0; }
}
.chart-line {
stroke-dasharray: 1000;
animation: drawChart linear both;
animation-timeline: scroll(root block);
}This approach offloads the calculation to the browser’s compositor thread, delivering 60+ FPS performance without JavaScript overhead.
4. Advanced Orchestration with Animation Libraries
For complex visualizations involving morphing shapes, coordinate updates, and multi-stage charts, platforms rely on dedicated libraries:
- GSAP (GreenSock) & ScrollTrigger: Allows
developers to pin SVG canvases and scrub through complex timeline
sequences, translating, rotating, and scaling individual SVG
<g>,<circle>, or<rect>nodes. - D3.js: Used to interpolate numerical data arrays
and recalculate SVG path definitions (
dattributes) based on scroll step milestones. - Scrollama / Intersection Observer: Fires discrete JavaScript callbacks when narrative sections enter the viewport, triggering targeted step-by-step SVG transitions.
5. Performance Optimization
Synchronizing SVGs with scrolling requires strict performance practices to avoid layout thrashing and dropped frames:
- Throttling via
requestAnimationFrame: Ensures scroll listeners only trigger DOM updates during the browser’s repaint cycle. - Transform Attributes: Animating CSS
transform(scale, translate, rotate) on SVG elements rather than layout attributes (x,y,width,height) allows the GPU to handle rendering. - Vector Simplification: Reducing the number of
control points in
<path>elements minimizes the computational cost of coordinate interpolation during rapid scrolling.