Docs
3D Card

3D Card

A 3D card component that can be used to display multiple items with animation.

HOVER OVER

components/snippet/3d-card.tsx
// @NOTE: in case you are using Next.js
"use client";
 
import React, { useRef } from "react";
import {
  motion,
  useMotionTemplate,
  useMotionValue,
  useSpring,
} from "framer-motion";
import { HomeIcon  } from "lucide-react";
 
 
const ROTATION_RANGE = 32.5;
const HALF_ROTATION_RANGE = 32.5 / 2;
 
const ThreeDCard = () => {
  const ref = useRef<HTMLDivElement | null>(null);
 
  const x = useMotionValue(0);
  const y = useMotionValue(0);
 
  const xSpring = useSpring(x);
  const ySpring = useSpring(y);
 
  const transform = useMotionTemplate`rotateX(${xSpring}deg) rotateY(${ySpring}deg)`;
 
  const handleMouseMove = (e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    if (!ref.current) return [0, 0];
 
    const rect = ref.current.getBoundingClientRect();
 
    const width = rect.width;
    const height = rect.height;
 
    const mouseX = (e.clientX - rect.left) * ROTATION_RANGE;
    const mouseY = (e.clientY - rect.top) * ROTATION_RANGE;
 
    const rX = (mouseY / height - HALF_ROTATION_RANGE) * -1;
    const rY = mouseX / width - HALF_ROTATION_RANGE;
 
    x.set(rX);
    y.set(rY);
  };
 
  const handleMouseLeave = () => {
    x.set(0);
    y.set(0);
  };
 
  return (
    <motion.div
      ref={ref}
      onMouseMove={handleMouseMove}
      onMouseLeave={handleMouseLeave}
      style={{
        transformStyle: "preserve-3d",
        transform,
      }}
      className="relative h-96 w-72 rounded-xl bg-gradient-to-br from-indigo-400 to-emerald-400"
    >
      <div
        style={{
          transform: "translateZ(75px)",
          transformStyle: "preserve-3d",
        }}
        className="absolute inset-4 grid place-content-center rounded-xl bg-gradient-to-br from-emerald-200 to-indigo-200 shadow-lg"
      >
        <HomeIcon
        size={64}
          style={{
            transform: "translateZ(75px)",
          }}
          className="mx-auto text-4xl text-black "
        />
        <p
          style={{
            transform: "translateZ(50px)",
          }}
          className="text-center text-2xl font-bold text-black  "
        >
          HOVER OVER
        </p>
      </div>
    </motion.div>
  );
};
 
export default ThreeDCard;