2.9 · Animation

3D Tilt on Hover.

Card tilts toward the cursor in 3D space. Inner content lifts on the Z axis. A glossy light reflection sweeps the surface. Apple-product-page energy.

What it is

Cards (or any element) rotate on the X and Y axes based on the cursor's position over them, creating an illusion that the card is a physical, slightly tilted object made of glass or metal. Inner elements (titles, icons) lift toward you on the Z axis for parallax depth. A radial-gradient light reflection tracks the cursor so the card looks polished. Used by Apple, Stripe, Linear, and almost every premium product page.

How it works

The card's parent gets perspective: 1400px. The card itself uses transform-style: preserve-3d so child elements can sit on different Z planes. On mousemove, JS calculates the cursor's offset from the card's center (–50% to +50% in each axis) and applies transform: rotateX(...)deg rotateY(...)deg. Inner elements use transform: translateZ(...) to float forward. A ::before pseudo-element with a radial-gradient at --mx / --my CSS variables provides the moving light reflection.

perspective: 1400pxApplied to the PARENT — controls how deep the 3D space feels
transform-style: preserve-3dLets child elements sit on different Z planes inside the card
rotateX + rotateYFrom mouse offset, ±10° in each direction is usually plenty
translateZ(40px)Inner elements float toward the camera — creates parallax depth

Live demo

Hover any card. Move the mouse around to feel the 3D tilt and watch the light reflect.

Live · hover & move
01 / Aurora
Compose anything.

The blank-page tool reimagined for teams.

02 / Pulse
Measure what matters.

Operator-grade dashboards, calmly delivered.

03 / Drift
Ship as you write.

From a doc to a deploy in one keystroke.

Copy this prompt

Prompt · 2.9 3D Card Tilt
Build a 3D tilt-on-hover card grid (3 cards). Parent container has perspective:1400px. Each card: aspect-ratio:3/4, transform-style:preserve-3d, will-change:transform, transition:transform 0.18s ease. On mousemove inside a card, JavaScript calculates cursor offset from the card's center as a percentage (-0.5 to +0.5 in each axis) and applies transform:rotateX(offsetY * -10deg) rotateY(offsetX * 10deg). On mouseleave, reset to rotateX(0) rotateY(0). Inner elements (title, icon, meta row) get transform:translateZ(40-60px) so they float toward the camera and parallax. Add a ::before pseudo-element with background:radial-gradient(280px circle at var(--mx) var(--my), rgba(255,255,255,0.45), transparent 60%) — update --mx and --my CSS variables on mousemove so the highlight tracks the cursor. opacity:0 by default, opacity:1 on hover. Cards are gradient-filled (violet, pink, cyan) with matching colored box-shadows.

Example sites to study