Open-source scroll animation for the web

MAKE THE PAGE
MOVE AS YOU SCROLL.

Draw SVG paths, reveal content, animate text, and scrub video with one tiny, dependency-free library. React, Vue, Svelte, Solid, Angular, Astro, and vanilla JS.

$npm i svg-scroll-draw
10 KBgzipped
0dependencies
SSRsafe
531 testspassing
MITlicensed

Live on this page

This page
draws itself.

The fountain pen illustration to the right isn't a video or a GIF. It's a live SVG animated by svg-scroll-draw — the exact same package you'd install. Scroll down and watch the ink ribbon draw out in real time.

showcase.tsx
<ScrollDraw
  selector=".ink-ribbon"
  easing="ease-out"
  speed={1.5}
>
  <svg>{/* fountain pen */}</svg>
</ScrollDraw>
Scroll to draw the ink ribbon

Why this one

Built for scroll,
and nothing else.

Purpose-built for scroll

Triggers, progress, callbacks, playback control, and reduced-motion handling are one consistent API — not a general animation engine you configure into a scroll tool.

Native when possible

Simple cases run on the compositor via CSS scroll timelines. Anything CSS cannot express falls back to the JS engine automatically. Your code never changes.

One package, every framework

First-class wrappers for React, Vue, Svelte, Solid, Angular, Astro, and Nuxt, plus vanilla JS and a web component — with zero runtime dependencies.

Bundle size

10 KB for the
complete toolkit.

Every library below is good at what it does. If you need a full animation platform, GSAP earns its size. This chart is about one thing only: what you ship when scroll animation is the job.

svg-scroll-draw✓ yours
10.0 KB gzip
Framer Motion
34.3 KB gzip
GSAP + ScrollTrigger + DrawSVG
47.5 KB gzip

Minified + gzipped. GSAP is free to use, DrawSVG included — this is a size comparison, not a price one. Full GSAP comparison →

Performance

Native CSS, with
a safety net.

On Chrome, Edge, and Firefox the simple draw case runs on the compositor via animation-timeline: view() zero per-frame JavaScript, no scroll listeners, no rAF loop. When the browser can't support it, the library falls back to the JS engine automatically. You never change your code.

Native CSS fast path

A default or named trigger, a named easing, optional fade, forward or reverse direction.

native.tsx
<ScrollDraw easing="ease-out" fade>
  <svg>...</svg>
</ScrollDraw>
// ✓ Uses animation-timeline: view()
your browser:
JS engine (auto fallback)

Callbacks, waypoints, stagger, morphing, spring easing, animated colour or width, custom containers — anything CSS can't express declaratively.

js-engine.tsx
<ScrollDraw native={false} easing="spring">
  <svg>...</svg>
</ScrollDraw>
// Forces JS engine regardless of browser

The full instance API — pause, resume, seek, replay, destroy — works on both paths. Full eligibility rules in the docs →

SVG path drawing

Drop in.
It just works.

Wrap any SVG with <ScrollDraw>. The engine finds every path, measures it, and animates it as it enters the viewport. No selectors, no IDs, no configuration.

index.tsx
import { ScrollDraw } from 'svg-scroll-draw/react';

export default function Hero() {
  return (
    <ScrollDraw>
      <svg>...</svg>
    </ScrollDraw>
  );
}
See the full example →

Easing

Speed — 1.0×

0.3× slow3× fast
v2.0.0 · scrollAnimate · interactive

Animate any CSS property.
Try it live.

Effect

opacity + translateY — the most common scroll entrance

Easing

Progress

0%
from stateto state
scroll-animate.js
import { scrollAnimate } from 'svg-scroll-draw';

scrollAnimate('#element', {
  props: {
    opacity: ['0', '1'],
    transform: ['translateY(36px)', 'translateY(0px)'],
  },
  easing: 'ease-out',
  once:   true,
});
scrollAnimate
Any CSS property.
Any element.
opacitytransformcolorbackground
npm i svg-scroll-draw

Drag the scrubber · switch effects · change easing

v2.2.0 · scrollText · interactive

Split text, stagger animate.
Free GSAP SplitText replacement.

Split by

Animation preset

opacity + translateY — the default entrance

Stagger

0.05
0 (all at once)0.10 (slowest cascade)

Progress

0%
hiddenfully revealed
scroll-text.js
import { scrollText } from 'svg-scroll-draw/text';

scrollText('#headline', {
  split:   'words',
  stagger: 0.05,
  from: {
    opacity: 0,
    y: 28,
  },
  once: true,
});
scrollText

Scroll-driven text animation. Every word, every letter, every line.

split:wordsstagger:0.05

Drag scrubber · switch split mode · change preset · adjust stagger

The rest of the toolkit

Beyond SVG.
Animate everything.

Read the docs →

Draw & morph

  • scrollDraw

    Draw any SVG path as it enters the viewport.

  • scrollDrawGroup

    Animate many SVGs together with shared options.

  • scrollDrawSequence

    Chain SVGs — each starts when the last finishes.

  • morphTo

    Interpolate one path shape into another.

Reveal & animate

  • scrollAnimate

    Animate any CSS property on any element.

  • scrollReveal

    One-line replacement for AOS and ScrollReveal.js.

  • scrollText

    Split text into chars, words or lines and stagger it.

Scroll experiences

  • scrollPin

    Pin an element while the page scrolls past it.

  • scrollSnap

    Section snapping with easing and callbacks.

  • scrollHorizontal

    Drive horizontal movement from vertical scroll.

  • scrollParallax

    Move an element at a fraction of scroll speed.

Media & data

  • scrollVideo

    Tie video currentTime to scroll position.

  • scrollCounter

    Count a number up as it scrolls into view.

  • scrollProgress

    Expose progress as a CSS custom property.

Tooling

  • devtools

    Dev-only overlay of every active animation.

  • Lenis bridge

    Works alongside smooth-scroll libraries.

  • CLI

    npx svg-scroll-draw init scaffolds a starting setup.

Every API above has a runnable example and a full options reference. Browse all 23 examples →

Quickstart

Works everywhere
you do.

Hero.tsx
import { ScrollDraw } from 'svg-scroll-draw/react';

export default function Hero() {
  return (
    <ScrollDraw easing="ease-out" speed={1.2}>
      <svg>...</svg>
    </ScrollDraw>
  );
}

BUILD YOUR FIRST
SCROLL ANIMATION
IN TWO MINUTES.

Open Playground →
npm i svg-scroll-draw
Read the docs →