WebberUI

Tilt Card

A 3D perspective tilt card — the card tilts with the cursor, a glare sweeps across its surface, it springs back on leave, and content can float up with translateZ.

Loading preview…
npx shadcn@latest add https://webberui.com/r/tilt-card.json

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

12
1.02
<TiltCard />

Installation

npx shadcn@latest add https://webberui.com/r/tilt-card.json

Installing also writes the --wb-duration-fast CSS variable into your global stylesheet.

Usage

import { TiltCard, TiltCardItem } from "@/components/ui/tilt-card";

<TiltCard maxTilt={12} scale={1.02}>
  <div className="h-40 rounded-t-xl bg-neutral-100 dark:bg-neutral-800" />
  <TiltCardItem z={40} className="p-5">
    <h3 className="font-semibold">Title</h3>
    <p className="text-sm text-neutral-500">This content floats 40px above the card face.</p>
  </TiltCardItem>
</TiltCard>

Props

TiltCard

PropTypeDefaultDescription
maxTiltnumber12Maximum tilt angle (degrees); rotateX / rotateY reach this angle when the cursor is at the card's edge
glarebooleantrueWhether to show the glare layer that follows the cursor
scalenumber1.02Scale factor on hover; 1 means no scaling
springConfigSpringOptions{ stiffness: 300, damping: 25, mass: 0.5 }Spring parameters shared by the tilt, scale, and spring back
classNamestringStyles for the card body (a neutral rounded card by default, overridable; do not add overflow-hidden)
childrenReactNodeCard content

Remaining <div> attributes (onClick, aria-*, and so on) are forwarded to the outer perspective container.

TiltCardItem

PropTypeDefaultDescription
znumber40Height the content floats toward the viewer along the Z axis (px)
classNamestringCustom styles
childrenReactNodeThe content to float

How it works

  • 3D perspective: the outer container is fixed at perspective: 1000px and the card body uses transform-style: preserve-3d; rotateX / rotateY map linearly to ±maxTilt based on the cursor's position relative to the center
  • Glare: a white radial-gradient highlight follows the cursor position, growing stronger the further the cursor is from the center (0 when dead-center, brighter the more the card tilts); the highlight color can be overridden with the --wb-tilt-glare CSS variable (default rgba(255, 255, 255, 0.4))
  • Spring back: every transform is driven by useMotionValue + useSpring, so once the cursor leaves the card springs back with momentum and the glare fades out
  • Floating layers: TiltCardItem uses translateZ to lift content off the card face; it must be a direct child of TiltCard, and if another container sits in between, give that container transform-style: preserve-3d
  • Avoid overflow-hidden: setting overflow-hidden on the card body flattens the 3D context (translateZ stops working), so for full-bleed images add the radius to the image itself instead (for example rounded-t-xl)
  • Stable, no jitter: pointer events are attached to the untransformed outer container, so the card never reads back its own transformed bounds mid-rotation and feeds jitter into the loop
  • Automatically disabled on touch devices: only mouse pointer events are handled (pointerType === "mouse"), so on touch it is just an ordinary card
  • When the user has "reduce motion" enabled at the system level, the tilt and glare are disabled; the card stays static and its content and functionality are unaffected

On this page