·2 min read

magnetic button effect.

An interactive button that follows the cursor with a magnetic pull effect — built with React and Motion for buttery smooth spring physics.

reactmotioninteraction

Magnetic Button Effect

Buttons that subtly follow your cursor create a delightful, almost physical interaction. The key is spring physics — not linear interpolation.

The Concept

When the cursor enters the button's bounding box, the button shifts toward the cursor position with a spring animation. On leave, it snaps back to center.

tsx
import { useRef, useState } from "react";
import { motion, useSpring, useTransform } from "motion/react";
 
export function MagneticButton({ children }: { children: React.ReactNode }) {
  const ref = useRef<HTMLButtonElement>(null);
  const [isHovered, setIsHovered] = useState(false);
 
  const x = useSpring(0, { stiffness: 150, damping: 15 });
  const y = useSpring(0, { stiffness: 150, damping: 15 });
 
  const handleMouseMove = (e: React.MouseEvent) => {
    if (!ref.current) return;
    const rect = ref.current.getBoundingClientRect();
    const centerX = rect.left + rect.width / 2;
    const centerY = rect.top + rect.height / 2;
 
    x.set((e.clientX - centerX) * 0.3);
    y.set((e.clientY - centerY) * 0.3);
  };
 
  const handleMouseLeave = () => {
    x.set(0);
    y.set(0);
    setIsHovered(false);
  };
 
  return (
    <motion.button
      ref={ref}
      style={{ x, y }}
      onMouseMove={handleMouseMove}
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={handleMouseLeave}
    >
      {children}
    </motion.button>
  );
}

Spring Physics

The magic is in the spring configuration:

  • stiffness: 150 — How quickly it responds. Higher = snappier.
  • damping: 15 — How quickly oscillation stops. Lower = bouncier.
  • 0.3 multiplier — How much the button actually moves. Keep it subtle.

Note: The motion/react import is the modern way to use Motion (previously Framer Motion). This is a drop-in replacement with the same API.

Considerations

  • Keep the movement subtle0.2–0.4 multiplier works best
  • Use this on CTAs and important buttons, not every clickable element
  • Disable on touch devices — magnetic effects don't translate to touch
  • Always spring back to (0, 0) on mouse leave