very page on the site replaces your system cursor with two small shapes: a tight dot that sits exactly where your pointer is, and a larger ring trailing a half-beat behind it. They're not decorative in the "looks nice" sense — the gap between them is the entire effect. A cursor that just is your pointer, one-to-one, is invisible. A second element trailing slightly behind reads as physical weight, the way a compass needle overshoots and settles rather than snapping straight to north.
Thetrailisn'tdrawnfromyourmouseevents.It'sdrawnfromaclock—thatdistinctionistheentiretrick.
Try it
move your cursor in here
The dot's position is set directly from the pointer coordinates on every mousemove — no delay, no smoothing. The ring is different: its position is recomputed every animation frame by nudging it 18% of the remaining distance toward wherever the dot currently is, whether or not the mouse actually moved that frame. That's a classic lerp — linear interpolation — running off requestAnimationFrame, completely decoupled from how often mousemove events actually fire.
typescript
let mouseX = 0, mouseY = 0; let trailX = 0, trailY = 0; const tick = () => { trailX += (mouseX - trailX) * 0.18; trailY += (mouseY - trailY) * 0.18; dot.style.transform = `translate3d(${mouseX}px, ${mouseY}px, 0)`; trail.style.transform = `translate3d(${trailX}px, ${trailY}px, 0)`; requestAnimationFrame(tick); };
Why not just animate it with CSS transitions
A CSS transition on the ring's position would look similar at a glance and cost nothing to write. It also can't be interrupted cleanly — retarget a transitioning element mid-flight and browsers handle the velocity discontinuity differently, which shows up as a visible stutter on fast, direction-changing mouse movement. The lerp has no such problem: every frame it just asks "where am I, where should I be," and closes 18% of that gap. Change direction mid-frame and the math doesn't care — it was never animating toward a fixed target in the first place, just continuously chasing a moving one.
It also only runs at all behind a matchMedia('(hover: hover) and (pointer: fine)') check, same as the magnetic buttons — a touch device has no persistent pointer position for a trailing ring to chase, so the whole thing never initializes there. No cursor replacement, no dead code paying a battery cost for an effect nobody on that device could ever see.