3D Flip Card - Interactive Card Component with CSS 3D Transforms

A beautiful 3D flip card component with realistic perspective transforms. Features hover and click triggers, multiple flip directions (horizontal, vertical, diagonal), various style variants, and fully responsive design. Perfect for profiles, products, pricing tables, and interactive content.

Installation

npx shadcn@latest add "https://ui-struct.vercel.app/r/flip-card"

Usage

import FlipCard from "@/components/ui/flip-card";
<FlipCard
front={<div>Front Content</div>}
back={<div>Back Content</div>}
/>

Preview

Hover over the card to see the 3D flip effect in action.

Hover Me

Move your cursor over this card to see the flip effect

Back Side

This is the back of the card with different content

Flip Directions

Three different flip directions: horizontal, vertical, and diagonal.

Horizontal

← Flip →

🔄

Vertical

↑ Flip ↓

🔃

Diagonal

↗ Flip ↙

🌀
DirectionEffect
horizontalFlips left to right (default)
verticalFlips top to bottom
diagonalFlips with a tilted perspective

Click Trigger

For mobile-friendly interactions, use click/tap instead of hover.

Click Me

Tap or click this card to flip it over

Tap to flip

Flipped!

Great! Click again to flip back

Tap to return

Style Variants

Four built-in style variants to match your design.

Default

variant: default

Lifted

variant: lifted

Glow

variant: glow

Gradient

variant: gradient-border

VariantDescription
defaultClean, minimal style
liftedElevated shadow on hover
glowBlue glow effect
gradient-borderAnimated gradient border

Profile Card

Perfect for team member profiles with social links on the back.

Profile

Numan Ahmed

Frontend Engineer

Building amazing products with React, TypeScript, and a lot of coffee ☕

124

Projects

8.2k

Followers

5yr

Experience

Connect with me

Hover out to flip back

Product Card

E-commerce product card with details revealed on flip.

Headphones-30%
Premium Audio

Wireless Pro Headphones

Immersive sound with active noise cancellation

$199$299

Click to see details →

Product Details

  • 40+ hours battery life
  • Active Noise Cancellation
  • Bluetooth 5.3 connectivity
  • Premium memory foam cushions
  • 2 year warranty included

Click to flip back

Pricing Cards

Compare pricing plans with flip interaction.

Basic
$9/month
  • 5 Projects
  • 10GB Storage
  • Email Support

Click to compare

Why Basic?

Perfect for individuals and small projects. Get started with essential features at an affordable price.

Best for

Freelancers & Hobbyists

POPULARPro
$29/month
  • Unlimited Projects
  • 100GB Storage
  • Priority Support
  • API Access

Click to compare

Why Pro?

Scale your business with advanced features, unlimited resources, and priority support.

Best for

Growing Teams & Startups

Responsive Grid

Fully responsive grid layout that works on all screen sizes.

Meet Our Team

Hover over a card to learn more

Sarah Chen

Sarah Chen

CEO & Founder

Sarah Chen

Visionary leader with 15+ years in tech

Marcus Johnson

Marcus Johnson

CTO

Marcus Johnson

Engineering wizard and problem solver

Emily Rodriguez

Emily Rodriguez

Design Lead

Emily Rodriguez

Creating beautiful user experiences

David Kim

David Kim

Product Manager

David Kim

Turning ideas into products

Props

PropTypeDefaultDescription
frontReactNode-Content for the front face
backReactNode-Content for the back face
flipDirection'horizontal' | 'vertical' | 'diagonal''horizontal'Direction of the flip
trigger'hover' | 'click''hover'How to trigger the flip
durationnumber0.6Animation duration in seconds
variant'default' | 'lifted' | 'glow' | 'gradient-border''default'Visual style variant
classNamestring-Additional CSS classes for the container

Accessibility

  • Use trigger="click" for better mobile and keyboard accessibility
  • The card maintains proper focus states
  • Content is readable in both flipped and unflipped states

Tips

  1. Set dimensions: Always wrap the FlipCard in a container with defined width and height
  2. Mobile: Use trigger="click" for touch devices
  3. Content overflow: Use overflow-hidden on front/back content to prevent clipping issues
  4. Images: Optimize images for the card size to ensure smooth animations

Full Code

'use client';
import { useState } from 'react';
import { motion } from 'framer-motion';
interface FlipCardProps {
front: React.ReactNode;
back: React.ReactNode;
className?: string;
flipDirection?: 'horizontal' | 'vertical' | 'diagonal';
trigger?: 'hover' | 'click';
duration?: number;
variant?: 'default' | 'lifted' | 'glow' | 'gradient-border';
}
export default function FlipCard({
front,
back,
className = '',
flipDirection = 'horizontal',
trigger = 'hover',
duration = 0.6,
variant = 'default',
}: FlipCardProps) {
const [isFlipped, setIsFlipped] = useState(false);
const getRotation = (flipped: boolean) => {
if (!flipped) return { rotateX: 0, rotateY: 0 };
switch (flipDirection) {
case 'horizontal':
return { rotateY: 180, rotateX: 0 };
case 'vertical':
return { rotateX: 180, rotateY: 0 };
case 'diagonal':
return { rotateY: 180, rotateX: 15 };
default:
return { rotateY: 180, rotateX: 0 };
}
};
const variantStyles = {
default: '',
lifted: 'hover:shadow-2xl',
glow: 'shadow-[0_0_30px_rgba(59,130,246,0.3)]',
'gradient-border': '',
};
const handleInteraction = () => {
if (trigger === 'click') {
setIsFlipped(!isFlipped);
}
};
const handleHoverStart = () => {
if (trigger === 'hover') {
setIsFlipped(true);
}
};
const handleHoverEnd = () => {
if (trigger === 'hover') {
setIsFlipped(false);
}
};
return (
<div
className={`relative w-full h-full ${className}`}
style={{ perspective: '1000px' }}
onClick={handleInteraction}
onMouseEnter={handleHoverStart}
onMouseLeave={handleHoverEnd}
>
{variant === 'gradient-border' && (
<div className="absolute -inset-[2px] rounded-2xl bg-gradient-to-r from-purple-500 via-pink-500 to-orange-500 opacity-75 blur-sm" />
)}
<motion.div
className="relative w-full h-full"
style={{ transformStyle: 'preserve-3d' }}
initial={false}
animate={getRotation(isFlipped)}
transition={{
duration,
type: 'spring',
stiffness: 100,
damping: 15,
}}
>
{/* Front Face */}
<div
className={`
absolute inset-0 w-full h-full rounded-2xl overflow-hidden
${variantStyles[variant]}
`}
style={{ backfaceVisibility: 'hidden' }}
>
{front}
</div>
{/* Back Face */}
<div
className={`
absolute inset-0 w-full h-full rounded-2xl overflow-hidden
${variantStyles[variant]}
`}
style={{
backfaceVisibility: 'hidden',
transform:
flipDirection === 'vertical' ? 'rotateX(180deg)' : 'rotateY(180deg)',
}}
>
{back}
</div>
</motion.div>
</div>
);
}