Docs
Hover Tilt Card
A Hover Tilt Card is a UI element that tilts dynamically based on the user's cursor movement, creating a 3D interactive effect.
Installation
Install dependencies
npm install framer-motion lucide-react
Run the following command
It will create a new file hover-tilt-card.tsx
inside the components/mage-ui/card
directory.
mkdir -p components/mage-ui/card && touch components/mage-ui/card/hover-tilt-card.tsx
Paste the code
Open the newly created file and paste the following code:
"use client";
import React, { useRef } from "react";
import {
motion,
useMotionTemplate,
useMotionValue,
useSpring,
} from "framer-motion";
import { FiMousePointer } from "react-icons/fi";
const HoverTiltCard = () => {
return (
<div className="grid w-full place-content-center bg-gradient-to-br from-indigo-500 to-violet-500 px-4 py-12 text-slate-900">
<TiltCard />
</div>
);
};
const ROTATION_RANGE = 32.5;
const HALF_ROTATION_RANGE = 32.5 / 2;
const TiltCard = () => {
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-300 to-violet-300"
>
<div
style={{
transform: "translateZ(75px)",
transformStyle: "preserve-3d",
}}
className="absolute inset-4 grid place-content-center rounded-xl bg-white shadow-lg"
>
<FiMousePointer
style={{
transform: "translateZ(75px)",
}}
className="mx-auto text-4xl"
/>
<p
style={{
transform: "translateZ(50px)",
}}
className="text-center text-2xl font-bold"
>
HOVER ME
</p>
</div>
</motion.div>
);
};
export default HoverTiltCard;