Tilt Card
A 3D tilt wrapper that applies a perspective tilt effect on mouse movement. Inspired by Motion Primitives’ Tilt. Wrap any Card or element for interactive depth.
Installation
Section titled “Installation”npx shadcn@latest add https://joaocarmassi.com/components/tilt.jsonpnpm dlx shadcn@latest add https://joaocarmassi.com/components/tilt.jsonnpx shadcn@latest add https://joaocarmassi.com/components/tilt.jsonbunx --bun shadcn@latest add https://joaocarmassi.com/components/tilt.jsonImport
Section titled “Import”import { Tilt } from '@/components/ui/tilt';Preview
Section titled “Preview”Tilt Card
Hover to see the 3D tilt effect.
Wrap any element with the Tilt component for interactive depth.
<Tilt rotationFactor={15} springOptions={{ stiffness: 300, damping: 20 }}> <Card className='w-72'> <CardHeader> <CardTitle>Tilt Card</CardTitle> <CardDescription>Hover to see the 3D tilt effect.</CardDescription> </CardHeader> <CardContent> <p className='text-sm text-muted-foreground'> Wrap any element with the Tilt component for interactive depth. </p> </CardContent> </Card></Tilt>Reversed Tilt
Section titled “Reversed Tilt”Reversed
Tilt moves opposite to cursor.
Use isReverse to invert the tilt direction.
<Tilt isReverse rotationFactor={20}> <Card>...</Card></Tilt>| Prop | Type | Default | Description |
|---|---|---|---|
children |
React.ReactNode |
— | Content to tilt. |
className |
string |
— | Additional CSS classes. |
style |
MotionStyle |
— | Motion style overrides. |
rotationFactor |
number |
15 |
Max rotation angle in degrees. |
isReverse |
boolean |
false |
Reverse the tilt direction. |
springOptions |
SpringOptions |
— | Spring animation config. |
DepthMedia
Section titled “DepthMedia”A companion component that places an image inside the Tilt card and gives it real parallax depth. A blurry, desaturated background layer and a sharp foreground layer shift at different rates as the card tilts, creating the illusion that the image has volume.
Installation
Section titled “Installation”npx shadcn@latest add https://joaocarmassi.com/components/depth-media.jsonpnpm dlx shadcn@latest add https://joaocarmassi.com/components/depth-media.jsonnpx shadcn@latest add https://joaocarmassi.com/components/depth-media.jsonbunx --bun shadcn@latest add https://joaocarmassi.com/components/depth-media.jsonImport
Section titled “Import”import { DepthMedia } from '@/components/ui/depth-media';Preview
Section titled “Preview”Place DepthMedia inside a positioned container (e.g. relative h-48) within a Tilt card and hover to see the parallax layers in action.
Depth Media
Hover to feel the parallax depth.
<Tilt rotationFactor={15} springOptions={{ stiffness: 300, damping: 20 }}> <Card className='w-72 overflow-hidden'> <div className='relative h-48'> <DepthMedia src='https://picsum.photos/288/192' alt='...' /> </div> <CardHeader> <CardTitle>Depth Media</CardTitle> <CardDescription>Hover to feel the parallax depth.</CardDescription> </CardHeader> </Card></Tilt>Depth Intensity
Section titled “Depth Intensity”Increase depthIntensity for more pronounced layer separation.
depthIntensity={4}
depthIntensity={16}
{ /* Subtle */}<DepthMedia src='...' depthIntensity={4} />;
{ /* Dramatic */}<DepthMedia src='...' depthIntensity={16} />;DepthMedia Props
Section titled “DepthMedia Props”| Prop | Type | Default | Description |
|---|---|---|---|
src |
string |
— | Image URL passed to the parallax image. |
alt |
string |
'' |
Accessible alt text for the foreground image. |
className |
string |
— | Additional CSS classes for the container. |
depthIntensity |
number |
8 |
Parallax multiplier — higher values increase layer shift. |
...img props |
Omit<ComponentProps<'img'>, 'src' | 'alt' | 'className'> |
— | Forwarded to the <img> (loading, sizes, decoding, etc.). |
Using image props
Section titled “Using image props”You can pass regular <img> props directly to DepthMedia.
<DepthMedia src='https://picsum.photos/288/192' alt='Mountain landscape' sizes='(max-width: 768px) 100vw, 288px' loading='lazy' decoding='async'/>