Motion pattern

Magnetic Button

A magnetic button is a call-to-action that tracks the user's cursor with spring-like easing, then releases back to its resting position when the cursor leaves. The effect makes the button feel alive without being distracting - it signals interactivity at a glance and rewards hover with a tactile response.

Updated June 1, 2026

Components

Components that solve this

Tradeoffs

Tuning the pattern

Spring strength
Lower (0.2-0.4) reads quiet and intentional. Higher (0.6-0.9) reads playful but can feel jittery on small movements.
Radius of pull
Larger radius (button width × 2) starts the pull early and feels more 'magnetic'. Smaller radius (button width × 0.8) reads as a quick snap rather than a magnetic pull.
Release ease
`expo.out` for snap-back feels responsive. `elastic.out(1, 0.5)` for overshoot feels bouncy. Pick by brand tone.
Label tracking
Optional: label can track at a fraction (0.5×) of the container's pull so the visual reads as 'button bends toward cursor, label catches up'. Subtle but distinctive.
When

When the magnetic button fits

The pattern works when you have a single, important CTA that you want users to notice and interact with. Common positions:

  • Hero CTA on a landing page
  • Primary action in a contact form
  • 'Start free trial' on a pricing page
  • Featured product card on a homepage

Avoid stacking magnetic buttons

When you have 5+ buttons in close proximity (a navigation row, a settings page), magnetic buttons compete with each other and the effect loses its meaning. Use a simple hover state for those - the effect rewards rarity.
Mechanics

How the pull works

A magnetic button has two layers of motion:

  • The container translates toward the cursor by a fraction of the cursor-offset (often 0.2-0.4). This is the 'pull'.
  • The label translates by a smaller fraction (often 0.5× the container) so it appears to lag slightly behind. This adds depth.

Both layers use gsap.quickTo for high-frequency cursor updates without a performance hit, and expo.out for the release when the cursor leaves.

script.js
In production

Annnimate components that solve this pattern

The Magnetic Button component handles the full pull + release + label-tracking + prefers-reduced-motion fallback. It accepts data attributes for tuning the strength (data-anm-strength="0.3"), the radius (data-anm-radius="200"), and the release ease. Available in React, Vue, and HTML/CSS/JS.

If you want a softer interpretation (the button reacts to cursor proximity without tracking), look at the hover-card component - same idea, different mechanism.

FAQ

Common questions

When should I use a magnetic button vs a simple hover state?
Use a magnetic button when the CTA matters enough to deserve real-estate (hero, single primary action per page, paid pricing CTA). Use a simple hover for everything else - 30 magnetic buttons on a page feels chaotic. The effect rewards rarity.
Does a magnetic button hurt accessibility?
Not if you do two things: (1) the button still receives focus and click events at its visual resting position (the pull is purely visual), and (2) you respect prefers-reduced-motion - skip the magnetic pull and fall back to a clean color/scale hover. Both are handled by default in the Annnimate component.
Does the magnetic effect work on touch devices?
Touch devices have no hover state, so the magnetic pull simply doesn't fire - the button reads as a normal button. Tap-and-press feedback is what matters on mobile; that's a separate concern handled by your own active/pressed styles.
Related patterns

Adjacent ideas in the patterns