Magnetic Button Effect

This magnetic button effect creates a satisfying interaction where the button seems to 'stick' to the user's cursor as they hover over it. It calculates the distance between the mouse position and the button's center to apply a translation, giving it a physical, weighty feel. Perfect for primary calls-to-action.

ReactFramer MotionTailwind

Installation

npm install framer-motion

Code

import { useRef, useState } from 'react';
import { motion } from 'framer-motion';

export default function MagneticButton() {
  const ref = useRef<HTMLDivElement>(null);
  const [position, setPosition] = useState({ x: 0, y: 0 });

  const handleMouse = (e: React.MouseEvent) => {
    const { clientX, clientY } = e;
    const { height, width, left, top } = ref.current!.getBoundingClientRect();
    const middleX = clientX - (left + width / 2);
    const middleY = clientY - (top + height / 2);
    setPosition({ x: middleX, y: middleY });
  }

  const reset = () => {
    setPosition({ x: 0, y: 0 });
  }

  const { x, y } = position;
  return (
    <motion.button
      ref={ref}
      animate={{ x, y }}
      transition={{ type: "spring", stiffness: 150, damping: 15, mass: 0.1 }}
      onMouseMove={handleMouse}
      onMouseLeave={reset}
      className="px-10 py-4 rounded-full bg-black text-white font-medium text-lg pointer-events-auto"
    >
      Hover Me
    </motion.button>
  )
}