Tilt card
Free · MITTilts toward the pointer on a spring with a moving glare, a shifting shadow and layers that float at their own depth.
Installation
$ npx shadcn@latest add https://goodui.dev/r/tilt-card.jsonThe file lands in components/goodui/tilt-card.tsx and is yours to edit. With the @goodui registry added, npx shadcn@latest add @goodui/tilt-card works too.
Usage
import { TiltCard, TiltCardLayer } from "@/components/goodui/tilt-card"
export function MembershipCard() {
return (
<TiltCard className="w-80 bg-gradient-to-br from-violet-600 to-indigo-700 p-6 text-white">
<TiltCardLayer depth={20}>
<p className="text-xs tracking-widest text-white/70 uppercase">Glow Studio</p>
</TiltCardLayer>
<TiltCardLayer depth={50} className="mt-10">
<p className="text-2xl font-semibold">Gold membership</p>
<p className="text-sm text-white/80">Unlimited blow-dries · 10% off color</p>
</TiltCardLayer>
<TiltCardLayer depth={30} className="mt-8 flex items-end justify-between">
<span className="text-sm">Maya Chen</span>
<span className="font-mono text-sm">$89/mo</span>
</TiltCardLayer>
</TiltCard>
)
}When to use
- Showcase cards on a landing page: a pricing plan, a product shot, a gift card or membership card.
- Cards with layered content (badge, avatar, price) that should float at different depths with TiltCardLayer.
- Portfolio and template galleries, where a tactile hover invites a click.
- A card that only needs a simple tilt plus variants, tones and header/footer parts: card with animation="tilt" is simpler. Use TiltCard for springs, glare control and depth layers.
- Data-heavy cards (tables, charts, forms): tilting makes text harder to read and click. Use card with animation="lift".
- Large grids of many cards: one tilting card draws the eye, twenty feel restless. Use spotlight-card with SpotlightGroup.
| If you need | Use |
|---|---|
| Subtle, app-friendly tilt | maxTilt={6} scale={1.01} |
| Dramatic showcase | maxTilt={15} perspective={600} |
| No glare | glare={false} |
| Floating badge or image | <TiltCardLayer depth={40}>…</TiltCardLayer> |
| Turn it off conditionally | disabled |
Examples
Calm pricing card
<TiltCard maxTilt={6} scale={1.01} glareOpacity={0.2} className="p-6" containerClassName="h-full">
<h3 className="font-semibold">Team</h3>
<p className="mt-2 text-3xl font-bold">$49<span className="text-base font-normal text-muted-foreground">/mo</span></p>
</TiltCard>API reference
TiltCard
| Prop | Type | Default |
|---|---|---|
| maxTilt Maximum tilt in degrees. | number | 10 |
| scale Scale while hovered. | number | 1.02 |
| glare Show a light glare that follows the pointer. | boolean | true |
| glareOpacity Peak opacity of the glare. | number | 0.35 |
| perspective CSS perspective in px; lower is more dramatic. | number | 900 |
| disabled Keep the card flat (no tilt, glare or scale). | boolean | false |
| containerClassName Classes for the outer element that holds the perspective and receives the pointer. | string | — |
Also accepts every <div> attribute.
TiltCardLayer
| Prop | Type | Default |
|---|---|---|
| depth How far the layer floats above the card, in px. | number | 30 |
Also accepts every <div> attribute.
Accessibility
- TiltCard renders two plain <div>s (a perspective container and the card); it adds no roles. Put real links or buttons inside for interaction.
- The glare layer is aria-hidden and ignores the pointer.
- Touch, keyboard and reduced-motion users get a flat card with the same content.
Motion
- The card rotates toward the pointer by up to `maxTilt` degrees (10) and scales to `scale` (1.02), on a spring (stiffness 220, damping 22, mass 0.6).
- A radial glare follows the pointer at up to `glareOpacity` (0.35), and the shadow shifts against the tilt and fades in on hover (spring, stiffness 200, damping 26).
- TiltCardLayer children float `depth` px (30) above the card with translateZ, so they move with parallax.
- Leaving the card springs it back flat. Touch input is ignored.
- Reduced motion or disabled: no tilt, scale, glare or shadow shift; the card stays flat.
- Pointer moves only set motion values, so React does not re-render. Effects use transform, opacity and box-shadow.
Notes for AI
Coding agents read these rules through MCP and llms.txt, or paste this page with Copy page.
- className styles the card (padding, background); containerClassName styles the outer element that holds the perspective and receives the pointer (sizing in grids, e.g. h-full).
- TiltCardLayer only floats when every element between it and the card keeps transform-style: preserve-3d and has no overflow: hidden.
- maxTilt is degrees, perspective and depth are px, scale is a factor (1.02 means 2% larger).
- The card already has rounded-xl, border, bg-card; override with className.
FAQ
Why is my layer not floating?
Some element between the layer and the card flattens 3D: overflow: hidden, or a wrapper without transform-style: preserve-3d. Make TiltCardLayer a direct child of TiltCard, or nest layers inside layers.
Core card animation="tilt" or TiltCard?
The Core card's tilt is a CSS transition with a light sheen and works with all card variants. TiltCard adds springs, a glare you can tune, a moving shadow and parallax layers.
Related
Eight surfaces (elevated, glass, gradient border, neo, inset…) with shadow, padding, radius and accent stripes, plus hover layers (lift, 3D tilt, pointer spotlight, glow, scale) and a looping border beam.
A soft spotlight and a lit border follow the pointer across a card; in a group, neighboring cards' borders light up too.
Button and its label are pulled toward a nearby cursor with a smooth falloff and spring back on leave; off for touch and reduced motion.
A slowly rotating gradient arc travels around the card border with a soft glow that intensifies on hover and focus.