3D Hover Card

Interactive card with 3D tilt effect on mouse movement

card3dhovertiltinteractive
Install dependencies
$npm install framer-motion
Preview

Source Code

"use client";

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

interface HoverCard3DProps {
  children: React.ReactNode;
  className?: string;
  maxTilt?: number;
}

export default function HoverCard3D({
  children,
  className = "",
  maxTilt = 15,
}: HoverCard3DProps) {
  const ref = useRef<HTMLDivElement>(null);
  const [rotate, setRotate] = useState({ x: 0, y: 0 });

  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
    if (!ref.current) return;
    const rect = ref.current.getBoundingClientRect();
    const x = (e.clientX - rect.left) / rect.width;
    const y = (e.clientY - rect.top) / rect.height;
    setRotate({
      x: (y - 0.5) * -maxTilt * 2,
      y: (x - 0.5) * maxTilt * 2,
    });
  };

  const handleMouseLeave = () => setRotate({ x: 0, y: 0 });

  return (
    <motion.div
      ref={ref}
      onMouseMove={handleMouseMove}
      onMouseLeave={handleMouseLeave}
      animate={{ rotateX: rotate.x, rotateY: rotate.y }}
      transition={{ type: "spring", stiffness: 300, damping: 20 }}
      style={{ perspective: 1000, transformStyle: "preserve-3d" }}
      className={`rounded-xl border border-white/10 bg-gradient-to-br from-white/10 to-white/5 p-6 backdrop-blur-sm ${className}`}
    >
      <div style={{ transform: "translateZ(40px)" }}>{children}</div>
    </motion.div>
  );
}