experiment 02
@aumiqx/scroll
A programmable scroll physics engine. Per-section friction, magnetic snap points, configurable mass. Pure math — no DOM, no framework, ~4KB, zero dependencies.
Every website on Earth uses identical scroll physics. This library lets you change all of it.
Every website scrolls exactly the same.
Same mass. Same friction. Same inertia. Your hero section and your footer have identical scroll physics. Try both boxes below — scroll in each one and feel the difference.
Normal Scroll
same friction everywhere
scroll here
Physics Scroll
per-section friction + magnets
scroll here
left: uniform friction 0.95 everywhere — right: hero resists, features glide, pricing snaps
Four steps, every frame.
The engine runs a physics loop at 60fps. No DOM manipulation — just pure math. You get a position number and decide what to do with it.
Force
Wheel or touch event applies force, divided by mass
Friction
Per-zone friction decays velocity each frame
Magnets
Nearby magnets pull position toward target
Position
Final position updates. You render it however you want.
velocity += force / mass | velocity *= zoneFriction | position += velocity
Feel the difference yourself.
Five sections, each with different physics. The velocity bar and zone indicator update in real time. Drag the mass slider to change how the whole thing feels.
Scroll feels HEAVY here. Every pixel matters. This is your first impression — the reader should sink into it, not fly past it.
friction: 0.82 — cinematic, heavy
Now scroll feels LIGHT. Momentum carries you. This is a gallery zone — users browse visually, skimming like flipping cards. One flick and you glide.
friction: 0.975 — featherlight, momentum
This section has a MAGNET. Try to scroll past it — the engine pulls you back to center. Pricing should never be skipped.
snap: true + magnet — can't skip this
Comfortable reading pace. Not too fast, not too slow. The friction is calibrated for trust-building content — testimonials, case studies.
friction: 0.93 — reading pace
Maximum resistance. Every scroll tick is HEAVY. Combined with a magnet, this section anchors the user. You can't casually scroll past it.
friction: 0.80 + magnet — anchored
scroll to feel different physics per section
physics
active zone
friction: 0.82 — cinematic, heavy
try this
1. Scroll fast — notice hero resists but features glides
2. Slow down near pricing — it grabs you
3. Set mass to 4 and flick — cinematic
4. Try reaching the cta — it fights you
each section has different physics — the velocity bar shows real-time momentum
~20 lines to get started.
Create an engine, feed it wheel events, call tick() on every frame. The engine gives you a position — you decide what moves.
import { ScrollEngine } from "@aumiqx/scroll"
const engine = new ScrollEngine({
mass: 1.2,
friction: 0.93,
zones: [
{ start: 0, end: 500, friction: 0.85 },
{ start: 500, end: 1000, friction: 0.97 },
{ start: 1000, end: 1500, snap: true },
],
magnets: [
{ position: 750, strength: 0.4, range: 120 },
],
})
element.addEventListener("wheel", (e) => {
engine.applyForce(e.deltaY * 0.3)
})
function tick() {
const { position } = engine.tick()
el.style.transform = `translateY(${-position}px)`
requestAnimationFrame(tick)
}
tick()applyForce(delta)Feed input from any event
tick()Advance physics by one frame
configure(opts)Change settings at runtime
It is not just for websites.
The engine outputs a number. Anything that responds to position can be driven by scroll physics.
Storytelling Landing Pages
Hero is slow and dramatic. Feature gallery is fast and fluid. CTA magnetically grabs and holds.
Cinematic WebGL Experiences
Drive a 3D camera with scroll. Mass creates Steadicam movements. Zones change camera speed at key moments.
Reading Experience Optimizer
Long-form articles auto-increase friction. Readers absorb more content without consciously stopping.
E-commerce Product Scroller
Product listings with physical momentum. Sale items slow you down. Magnetic snap on checkout CTA.
Interactive Data Visualization
Scroll drives chart progression. Zones map to datasets. Magnetic points on major data events.
Scroll-Driven Games
Platformers, runners, puzzles — controlled entirely by scroll physics. The scroll engine becomes the game engine.
For the technically curious.
Every configuration option and method, at a glance.
~4KB
bundle
0
dependencies
no
dom required
none
framework
configuration
| option | type | default | description |
|---|---|---|---|
| mass | number | 1 | Scroll inertia. Higher = more momentum, slower response. |
| friction | number | 0.95 | Base velocity decay per frame. 0.80 = stops fast. 0.99 = glides. |
| min / max | number | 0 / Inf | Scroll bounds. Hitting bounds causes a bounce. |
| zones | ScrollZone[] | [] | Per-section friction overrides and snap behavior. |
| magnets | ScrollMagnet[] | [] | Points that pull scroll toward them when in range. |
| walls | ScrollWall[] | [] | Custom bounce points with configurable elasticity. |
api
applyForce(delta)Apply external force (wheel/touch). Divided by mass.
tick()Advance physics one frame. Returns position, velocity, zone, magnet, bounce state.
setPosition(pos)Teleport to position. Resets velocity.
configure(opts)Update mass, friction, zones, magnets at runtime.
.positionCurrent scroll position (getter).
.velocityCurrent velocity in px/frame (getter).
.stateFull state snapshot (getter).
ScrollZone
{
start: number,
end: number,
friction?: number, // 0.80-0.99
snap?: boolean // pull to center
}ScrollMagnet
{
position: number, // target px
strength: number, // 0-1 pull force
range: number // activation radius
}built by aumiqx labs