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:

  1. Start Point: The top of the container enters the viewport.
  2. Current Progress: Calculated as progress = (currentScroll - startScroll) / totalScrollDistance.
  3. 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:

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:

5. Performance Optimization

Synchronizing SVGs with scrolling requires strict performance practices to avoid layout thrashing and dropped frames: