@vysmo/scroll Library DOM

Scroll for the modern web.

Three primitives that bind scroll progress to the rest of the ecosystem: createScrollProgress (raw 0–1 emitter), createScrollTransition (drives any @vysmo/transitions render), createScrollEffect (drives any @vysmo/effects params). One shared rAF-throttled observer underneath.

  • 3 primitives
  • ~1 KB gzipped
  • 1 rAF shared observer
  • headless you own the canvas
$ pnpm add @vysmo/scroll View on GitHub
createScrollProgress

Low-level emitter — 0 when the section enters the viewport from below, 1 when it exits through the top. Remap with ease for any non-linear progress.

progress0.000
createScrollTransition

Scroll progress drives a transition through three zones. Entry zone: transition plays 0 → 1. Clear zone: holds at the to image. Exit zone: plays back1 → 0. The green band on the bar is the clear zone — drag the handles to reshape it.

Transition
createScrollEffect

Scroll progress drives effect params through a three-zone envelope from scrollZones(clearStart, clearEnd). Effect ramps in as the section enters, sits at identity through the clear zone, ramps back as it exits. The dark band on the bar is where the image is fully clean.

Effect
size 1.0 px

Two patterns to start with

Drive any value off scroll with createScrollProgress, or hand a @vysmo/transitions / @vysmo/effects runner to the dedicated primitives and let them re-render on every frame the position changes.

Drive any value

import { createScrollProgress } from "@vysmo/scroll";

const handle = createScrollProgress({
  element: document.querySelector("#hero")!,
  onProgress: (p) => element.style.opacity = String(p),
});

Scroll-driven transition

import { createScrollTransition, scrollPlateau } from "@vysmo/scroll";
import { Runner, crossZoom } from "@vysmo/transitions";

const runner = new Runner({ canvas });
createScrollTransition({
  section,
  runner,
  transition: crossZoom,
  from, to,
  ease: scrollPlateau(0.3, 0.7), // hold the "to" image mid-section
});

Built for

Scroll-driven hero transitions

Two images that morph as the visitor scrolls past. Pair with @vysmo/transitions for the shader; the scrollPlateau envelope holds the final frame across the middle of the section.

Reveal effects on entry / exit

Blur, pixelate, or chromatic-aberrate an image as it enters and exits the viewport, identity in the middle. The scrollZones bathtub envelope is purpose-built for this — minimal eye-candy where it matters, clean where the user is reading.

Page-flip storytelling

Drive @vysmo/flipbook's seek() off scroll progress for cinematic page reveals tied to scroll position — books and lookbooks that turn as the visitor scrolls down the page.

Long-form articles

Pin diagrams or charts in view, animate them as the reader progresses through the surrounding paragraphs. Scroll progress is the universal storytelling clock on the web.

Product / case-study showcases

Driven sequences: image fades in, gets a soft blur as the reader continues, then ramps to a different shot — without the build-your-own scroll-driven plumbing. One observer, one callback per section.

Bring your own renderer

The shared rAF-throttled observer and zone helpers are useful even if you ship your own canvas / DOM rendering — subscribe via sharedScrollObserver() and you get the same one-rAF batching as the rest of the ecosystem.