Skip to content

Flip Card

A 3D flip wrapper that accepts two shadcn Card components as its front and back faces and applies a smooth Y-axis rotation. Works in hover mode (default) or controlled mode via the isFlipped prop, inspired by Kokonut UI’s Card Flip.

Terminal window
npx shadcn@latest add https://joaocarmassi.com/components/flip-card.json
import { FlipCard } from '@/components/ui/flip-card';
import {
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
} from '@/components/ui/card';

Front Face
Hover to reveal the back.

This is the front side of the card.

Back Face
Content revealed on hover.

The back face can have a completely different style.

<FlipCard
className='h-70 w-75'
front={
<Card className='h-full'>
<CardHeader>
<CardTitle>Front Face</CardTitle>
<CardDescription>Hover to reveal the back.</CardDescription>
</CardHeader>
<CardContent>
<p className='text-sm text-muted-foreground'>
This is the front side of the card.
</p>
</CardContent>
</Card>
}
back={
<Card className='h-full bg-primary text-primary-foreground'>
<CardHeader>
<CardTitle>Back Face</CardTitle>
<CardDescription className='text-primary-foreground/70'>
Content revealed on hover.
</CardDescription>
</CardHeader>
<CardContent>
<p className='text-sm text-primary-foreground/70'>
The back face can have a completely different style.
</p>
</CardContent>
</Card>
}
/>

Pricing
Pro
Hover to see what's included.

$29/mo

What's included
  • ✓ Unlimited projects
  • ✓ Priority support
  • ✓ Custom domain
<FlipCard
className='h-75 w-75'
front={<Card className='h-full'>...</Card>}
back={<Card className='h-full'>...</Card>}
/>

Pass isFlipped to control the flip with external state. When provided, hover has no effect.

Front Face
Click the button to flip.

This is the front side of the card.

Back Face
Controlled via state.

The flip is driven by isFlipped.

import { useState } from 'react';
const [flipped, setFlipped] = useState(false);
<div className='flex flex-col items-center gap-4'>
<FlipCard
className='h-70 w-75'
isFlipped={flipped}
front={<Card className='h-full'>...</Card>}
back={<Card className='h-full'>...</Card>}
/>
<Button onClick={() => setFlipped((f) => !f)}>
{flipped ? 'Show Front' : 'Show Back'}
</Button>
</div>;

  • The FlipCard container requires an explicit height (and optionally width) via className — e.g. className="h-70 w-75".
  • Both front and back Cards should include className="h-full" to fill the container.
  • Hover mode (default): the flip is triggered on hover when isFlipped is not provided.
  • Controlled mode: pass isFlipped to drive the flip from external state; hover is disabled.

Prop Type Default Description
front React.ReactNode Content rendered on the front face
back React.ReactNode Content rendered on the back face
isFlipped boolean undefined Controls flip state externally. When omitted, hover triggers the flip
className string Applied to the outer container (set height here)