scroll-craft v0.1

Scroll animation
that ships.

Zero dependencies. ~4KB. IntersectionObserver-powered reveals, counters, progress fills, staggers, zooms, and text reveals — all in TypeScript.

npm install scroll-craft
0 dependencies TypeScript Tree-shakeable
RevealEffect 01

Animate elements into view from any direction with configurable easing, distance, and delay.

import { reveal } from 'scroll-craft' reveal('.card', { direction: 'up', distance: '32px', duration: 600, ease: 'cubicOut', delay: 0, })
0%
Satisfaction
0+
Projects
0
Deps
CounterEffect 02

Count from zero to any number when the element enters the viewport. Custom formatter support.

import { counter } from 'scroll-craft' counter('[data-count]', { duration: 1400, ease: 'cubicOut', formatter: (n) => n.toLocaleString('en-US'), })
0101
Extract your scroll logic
0202
Package with TypeScript
0303
Publish to npm
ProgressEffect 03

Fill child elements with clip-path as steps scroll through the viewport — or trigger on replay.

import { progress } from 'scroll-craft' progress('#timeline .step', { start: 0.82, end: 0.2, fillSelector: '.sc-fill', })

Words arrive one beat at a time.

Letters cascade with stagger.

Text RevealEffect 04

Split text into word or letter spans and stagger each into view. Accessible — nested elements stay intact.

import { textReveal } from 'scroll-craft' textReveal('.headline', { type: 'words', stagger: 40 }) textReveal('.eyebrow', { type: 'letters', stagger: 18 })
01
02
03
StaggerEffect 05

Observe a parent and cascade its children into view one after another with a configurable delay.

import { stagger } from 'scroll-craft' stagger('.grid', { children: '.card', direction: 'up', stagger: 80, duration: 600, })
Soft focus
on arrival.
Blur RevealEffect 06

Fade, de-blur, and lift elements into clarity as they enter the viewport. Great for hero panels.

import { blurReveal } from 'scroll-craft' blurReveal('.panel', { blur: '12px', distance: '16px', duration: 700, })
01
02
ZoomEffect 07

Scale elements from a smaller starting point while fading them in. Stays on the compositor path.

import { zoom } from 'scroll-craft' zoom('.card', { from: 0.92, duration: 600, ease: 'cubicOut', })
0%
Tied to page scroll position
Scroll ProgressEffect 08

Bind any CSS property (width, scale, opacity) to the page or container scroll position in real time.

import { scrollProgress } from "scroll-craft" scrollProgress(".bar", { axis: "y", property: "scale", })
01
Brief
02
Build
03
Launch
SceneEffect 09

Timeline-based scroll animation — define steps with from/to states and map them to scroll progress through a section.

import { scene } from "scroll-craft" scene(".section", [ { target: ".step-1", from: { opacity: 0 }, to: { opacity: 1 }, start: 0, end: 0.3 }, { target: ".step-2", from: { opacity: 0 }, to: { opacity: 1 }, start: 0.3, end: 0.6 }, ])
ParallaxEffect 10

Move elements at a different speed to the scroll. Configurable axis, speed, and clamping.

import { parallax } from "scroll-craft" parallax(".hero-bg", { speed: 0.3, axis: "y", clamp: 80, })
import { ScrollCraft } from "scroll-craft"

const sc = new ScrollCraft()

sc.reveal(".hero", { direction: "up" })
  .blurReveal(".panel", { blur: "12px" })
  .counter("[data-count]", { duration: 1200 })
  .progress("#timeline .step")
  .stagger(".grid", { children: " .card" })
  .textReveal(".headline", { type: "words" })
  .zoom(".product", { from: 0.94 })
  .parallax(".bg", { speed: 0.3 })

// clean up all observers + listeners
sc.destroy()
Chainable APIScrollCraft class

All effects are available on a single ScrollCraft instance. Chain them together and call .destroy() to disconnect all observers and scroll listeners at once.