3D Tilt Effect
The 3D Tilt Effect is an interactive visual technique that makes cards or images respond to mouse movements, creating a perspective effect. When a user moves their cursor over the card, it appears to tilt as if it were a 3D object. This effect is achieved through mouse tracking and perspective transform techniques, allowing the card to subtly bend in response to the user’s actions.
Zoe Garcia
Backend DeveloperInstallation
Install the following dependencies:
npm i framer-motion clsx tailwind-merge
Add util file
import { ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Copy and paste the following code into your project.
"use client";
import React, { useRef } from "react";
import {
motion,
useMotionTemplate,
useMotionValue,
useSpring,
} from "framer-motion";
import { cn } from "@/lib/utils";
type Props = { children: React.ReactNode; className?: string };
const ROTATION_RANGE = 32.5;
const HALF_ROTATION_RANGE = 32.5 / 2;
export function Three3DTiltEffect({ children, className }: Props) {
const ref = useRef<HTMLDivElement>(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>) => {
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={cn("w-72", className)}
>
{children}
</motion.div>
);
}
Usage
import { Three3DTiltEffect } from "@/components/ui/3d-tilt-effect";
import Image from "next/image";
export default function ThreeDTiltEffectExample() {
return (
<>
<Three3DTiltEffect>
<div className="bg-background rounded-xl overflow-hidden border group/hoverimg shadow-lg">
<div className="h-full overflow-hidden">
<Image
src="https://cosmic.shadcnuikit.com/_next/image?url=https%3A%2F%2Fimages.unsplash.com%2Fphoto-1573497019940-1c28c88b4f3e%3Fq%3D80%26w%3D1587%26auto%3Dformat%26fit%3Dcrop%26ixlib%3Drb-4.0.3%26ixid%3DM3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%253D%253D&w=384&q=75"
alt=""
width={300}
height={300}
className="w-full aspect-square object-cover transition-all duration-200 ease-linear size-full"
/>
</div>
<div className="flex flex-col py-6 px-6">
<div className="text-xl">Zoe Garcia</div>
<span className="text-muted-foreground">Backend Developer</span>
</div>
</div>
</Three3DTiltEffect>
</>
);
}