Pointer · effect

MagneticButton

An element that leans towards the cursor before the cursor arrives.

move the cursor near the button, not onto it

Paste into Claude Code, Cursor or any agent. Pinned to a tag, so it will not change under you.

Options

reach 1.1

0 to 4, good: 0.6 to 1.6

How far outside the element the pull starts, as a multiple of its own size. 1 is one element-width of empty space around it. Large values on a small button make it twitch at things happening on the other side of the page.

strength 0.34

0 to 1, good: 0.2 to 0.5

How far the element travels towards the cursor, as a fraction of the gap. Above 0.6 the cursor can never catch it, which is funny once and annoying afterwards.

maxShift 26

0 to 120 px, good: 15 to 40

Cap on the travel, whatever the strength works out to. This is what stops a wide element sliding out of its own layout.

scale 1.04

0.9 to 1.4, good: 1 to 1.08

Scale at full pull. 1 is no growth.

rotate 0

0 to 20 deg, good: 0 to 6

Degrees of lean at full pull, following the cursor left and right. Off by default: on text it reads as a wobble rather than a lean.

ease 420

0 to 1500 ms, good: 280 to 600

How long it takes to follow the cursor, and to let go. Low is a rubber band; high is treacle. The release matters more than the catch.

reducedMotionTime 0

0 to 60 s

The single frame shown when the user prefers reduced motion. At rest there is no pointer, so this draws the element unmoved, which is the right answer.

What it needs

Dependencies
None at all
Browser
No WebGL
Frame budget
~0.15 ms · 0 context
Pinned to
v0.6.2
  • No canvas and no WebGL. One CSS transform
  • Reads the pointer at window scope, because the point is reacting to a cursor that is still outside the element
  • The easing is a CSS transition rather than a per-frame spring, so nothing integrates and renderAtTime stays pure
  • Composited transform only
  • One getBoundingClientRect per frame while the cursor is in range, and none when it is not