Dependencies
tailwindcssshadcn/uilucide-react
shadcn/ui components
npx shadcn@latest add cardnpx shadcn@latest add badgenpx shadcn@latest add button

shadcn/ui's Card component provides a solid foundation for every card layout. These 5 examples cover the most common patterns — basic, stats, profile, pricing and hover effects.

Installation

npx shadcn@latest add card badge button
npm install lucide-react

Card Anatomy

import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"

<Card>
  <CardHeader>
    <CardTitle>Title</CardTitle>
    <CardDescription>Subtitle or description</CardDescription>
  </CardHeader>
  <CardContent>Main content area</CardContent>
  <CardFooter>Footer actions</CardFooter>
</Card>

Key Tailwind Classes for Cards

ClassWhat It Does
shadow-smSubtle card shadow
hover:shadow-xlShadow on hover
hover:-translate-y-1.5Lift effect on hover
transition-all duration-300Smooth animations
overflow-hiddenClips image zoom to card
groupEnables group-hover children

1. Basic shadcn/ui Card

The standard shadcn/ui Card with CardHeader, CardContent and CardFooter.

tsx
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"

export default function BasicCard() {
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 gap-4 max-w-2xl">
      {/* Simple card */}
      <Card>
        <CardHeader>
          <CardTitle>Marvel Angular Dashboard</CardTitle>
          <CardDescription>Angular 21 + Bootstrap 5 admin template</CardDescription>
        </CardHeader>
        <CardContent>
          <p className="text-sm text-muted-foreground">
            50+ components, dark mode, RTL support and 4 layout variants included.
          </p>
        </CardContent>
        <CardFooter className="flex justify-between items-center">
          <span className="font-bold text-lg" style={{ color: "#fd4766" }}>$29</span>
          <Button size="sm" style={{ background: "#fd4766" }}>Buy Now</Button>
        </CardFooter>
      </Card>

      {/* Card with badge */}
      <Card>
        <CardHeader>
          <div className="flex justify-between items-start">
            <div>
              <CardTitle>PORTO Bootstrap 5</CardTitle>
              <CardDescription>Multipurpose Bootstrap template</CardDescription>
            </div>
            <Badge style={{ background: "#fd4766" }}>Best Seller</Badge>
          </div>
        </CardHeader>
        <CardContent>
          <p className="text-sm text-muted-foreground">
            152 sales, 5.0 rating. Clean design with extensive documentation.
          </p>
        </CardContent>
        <CardFooter className="flex justify-between items-center">
          <span className="font-bold text-lg" style={{ color: "#fd4766" }}>$19</span>
          <Button variant="outline" size="sm">Preview</Button>
        </CardFooter>
      </Card>
    </div>
  )
}

2. React Stats Card

Dashboard metric cards with trend indicators using shadcn/ui and Lucide icons.

tsx
import { Card, CardContent } from "@/components/ui/card"
import { TrendingUp, TrendingDown, Users, DollarSign, Download, Star } from "lucide-react"

const stats = [
  {
    title: "Total Revenue",
    value: "$12,480",
    change: "+8.2%",
    trend: "up",
    icon: DollarSign,
    color: "#10b981",
  },
  {
    title: "Downloads",
    value: "3,240",
    change: "-2.4%",
    trend: "down",
    icon: Download,
    color: "#fd4766",
  },
  {
    title: "Active Users",
    value: "1,847",
    change: "+12.5%",
    trend: "up",
    icon: Users,
    color: "#4f6ef7",
  },
  {
    title: "Avg Rating",
    value: "4.9",
    change: "+0.1",
    trend: "up",
    icon: Star,
    color: "#f59e0b",
  },
]

export default function StatsCards() {
  return (
    <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
      {stats.map((stat) => {
        const Icon = stat.icon
        const TrendIcon = stat.trend === "up" ? TrendingUp : TrendingDown
        return (
          <Card key={stat.title} className="border-0 shadow-sm">
            <CardContent className="p-4">
              <div className="flex justify-between items-start mb-3">
                <p className="text-sm text-muted-foreground">{stat.title}</p>
                <div
                  className="w-9 h-9 rounded-lg flex items-center justify-center"
                  style={{ background: stat.color + "18" }}
                >
                  <Icon size={18} style={{ color: stat.color }} />
                </div>
              </div>
              <p className="text-2xl font-bold">{stat.value}</p>
              <div className="flex items-center gap-1 mt-1">
                <TrendIcon
                  size={14}
                  className={stat.trend === "up" ? "text-green-500" : "text-red-500"}
                />
                <span
                  className="text-xs font-medium"
                  style={{ color: stat.trend === "up" ? "#10b981" : "#ef4444" }}
                >
                  {stat.change}
                </span>
                <span className="text-xs text-muted-foreground">vs last month</span>
              </div>
            </CardContent>
          </Card>
        )
      })}
    </div>
  )
}

3. React Profile Card

User profile card with avatar, bio, stats and action buttons.

tsx
import { Card, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { MapPin, Link2, Twitter } from "lucide-react"

export default function ProfileCard() {
  return (
    <Card className="border-0 shadow-sm max-w-sm overflow-hidden">
      {/* Cover */}
      <div
        className="h-24"
        style={{ background: "linear-gradient(135deg, #fd4766, #4f6ef7)" }}
      />

      <CardContent className="p-4 pt-0">
        {/* Avatar */}
        <div
          className="w-16 h-16 rounded-full border-4 border-white flex items-center justify-content-center text-white font-bold text-lg shadow-sm"
          style={{ background: "#fd4766", marginTop: "-32px" }}
        >
          GS
        </div>

        <div className="mt-3">
          <h3 className="font-bold text-lg">Gagan Singh</h3>
          <p className="text-muted-foreground text-sm">Founder @ LettStart Design</p>

          <p className="text-sm mt-2 text-gray-600">
            Building Angular + Bootstrap admin templates. 10+ years of frontend experience.
          </p>

          <div className="flex gap-3 mt-3 text-xs text-muted-foreground">
            <div className="flex items-center gap-1">
              <MapPin size={12} /> India
            </div>
            <div className="flex items-center gap-1">
              <Link2 size={12} />
              <a href="https://lettstartdesign.com" className="hover:underline" style={{ color: "#fd4766" }}>
                lettstartdesign.com
              </a>
            </div>
          </div>

          <div className="flex gap-4 mt-4 py-3 border-y">
            {[
              { label: "Templates", value: "48" },
              { label: "Followers", value: "1.2K" },
              { label: "Sales", value: "5K+" },
            ].map((s) => (
              <div key={s.label} className="text-center flex-1">
                <p className="font-bold text-sm">{s.value}</p>
                <p className="text-xs text-muted-foreground">{s.label}</p>
              </div>
            ))}
          </div>

          <div className="flex gap-2 mt-4">
            <Button className="flex-1" style={{ background: "#fd4766" }}>Follow</Button>
            <Button variant="outline" size="icon">
              <Twitter size={16} />
            </Button>
          </div>
        </div>
      </CardContent>
    </Card>
  )
}

4. React Pricing Card

Pricing plan cards with featured plan highlight and feature lists.

tsx
import { Card, CardContent, CardHeader } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { Check } from "lucide-react"

const plans = [
  {
    name: "Free",
    price: "$0",
    desc: "For individuals",
    features: ["5 projects", "1GB storage", "Community support"],
    missing: ["Custom domain", "Analytics"],
    cta: "Get Started",
    featured: false,
  },
  {
    name: "Pro",
    price: "$29",
    desc: "For professionals",
    features: ["50 projects", "50GB storage", "Priority support", "Custom domain", "Analytics"],
    missing: [],
    cta: "Start Pro Trial",
    featured: true,
  },
  {
    name: "Team",
    price: "$99",
    desc: "For teams",
    features: ["Unlimited projects", "500GB storage", "Dedicated support", "Custom domain", "Advanced analytics"],
    missing: [],
    cta: "Contact Sales",
    featured: false,
  },
]

export default function PricingCards() {
  return (
    <div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-4xl">
      {plans.map((plan) => (
        <Card
          key={plan.name}
          className={`relative ${plan.featured ? "border-2 shadow-lg" : "border shadow-sm"}`}
          style={plan.featured ? { borderColor: "#fd4766" } : {}}
        >
          {plan.featured && (
            <div
              className="absolute -top-3 left-1/2 -translate-x-1/2 px-3 py-1 text-white text-xs font-semibold rounded-full"
              style={{ background: "#fd4766" }}
            >
              Most Popular
            </div>
          )}
          <CardHeader className="pb-4">
            <h3 className="font-bold text-lg">{plan.name}</h3>
            <p className="text-sm text-muted-foreground">{plan.desc}</p>
            <div className="mt-2">
              <span className="text-3xl font-bold" style={{ color: plan.featured ? "#fd4766" : undefined }}>
                {plan.price}
              </span>
              <span className="text-sm text-muted-foreground">/mo</span>
            </div>
          </CardHeader>
          <CardContent>
            <ul className="space-y-2 mb-6">
              {plan.features.map((f) => (
                <li key={f} className="flex items-center gap-2 text-sm">
                  <Check size={14} className="text-green-500 flex-shrink-0" /> {f}
                </li>
              ))}
              {plan.missing.map((f) => (
                <li key={f} className="flex items-center gap-2 text-sm text-muted-foreground">
                  <span className="w-3.5 text-center text-xs">✕</span> {f}
                </li>
              ))}
            </ul>
            <Button
              className="w-full"
              variant={plan.featured ? "default" : "outline"}
              style={plan.featured ? { background: "#fd4766", border: "none" } : {}}
            >
              {plan.cta}
            </Button>
          </CardContent>
        </Card>
      ))}
    </div>
  )
}

5. React Hover Card with Tailwind Animation

Interactive card with lift effect, image zoom on hover and overlay reveal.

tsx
import { Card } from "@/components/ui/card"
import { Badge } from "@/components/ui/badge"
import { ExternalLink } from "lucide-react"

const templates = [
  {
    name: "Marvel Angular Dashboard",
    framework: "Angular 21",
    price: "$29",
    badge: "Best Seller",
    color: "#fd4766",
    image: "https://picsum.photos/400/240?random=10",
  },
  {
    name: "PORTO Bootstrap Template",
    framework: "Bootstrap 5",
    price: "$19",
    badge: "5.0 ★",
    color: "#7952b3",
    image: "https://picsum.photos/400/240?random=11",
  },
  {
    name: "Proctu Medical React",
    framework: "React 19",
    price: "$39",
    badge: "New",
    color: "#10b981",
    image: "https://picsum.photos/400/240?random=12",
  },
]

export default function HoverCards() {
  return (
    <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
      {templates.map((t) => (
        <div
          key={t.name}
          className="group relative overflow-hidden rounded-xl border bg-white shadow-sm cursor-pointer transition-all duration-300 hover:-translate-y-1.5 hover:shadow-xl"
        >
          {/* Image with zoom */}
          <div className="relative overflow-hidden h-40">
            <img
              src={t.image}
              alt={t.name}
              className="w-full h-full object-cover transition-transform duration-500 group-hover:scale-110"
            />
            {/* Overlay on hover */}
            <div className="absolute inset-0 bg-black/60 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center gap-2">
              <a
                href="#"
                className="px-3 py-1.5 bg-white text-gray-900 text-xs font-semibold rounded-md hover:bg-gray-100"
              >
                Preview
              </a>
              <a
                href="https://lettstartdesign.com"
                className="px-3 py-1.5 text-white text-xs font-semibold rounded-md flex items-center gap-1"
                style={{ background: t.color }}
                target="_blank"
                rel="noopener"
              >
                Buy <ExternalLink size={10} />
              </a>
            </div>

            {/* Badge */}
            <div className="absolute top-2 left-2">
              <span
                className="px-2 py-0.5 text-white text-xs font-semibold rounded"
                style={{ background: t.color }}
              >
                {t.badge}
              </span>
            </div>
          </div>

          {/* Content */}
          <div className="p-3">
            <p className="text-xs text-muted-foreground mb-0.5">{t.framework}</p>
            <h3 className="font-semibold text-sm">{t.name}</h3>
            <div className="flex justify-between items-center mt-2">
              <span className="font-bold" style={{ color: t.color }}>{t.price}</span>
              <ExternalLink size={14} className="text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity" />
            </div>
          </div>
        </div>
      ))}
    </div>
  )
}

Frequently Asked Questions

Run npx shadcn@latest add card. This creates components/ui/card.tsx in your project with Card, CardHeader, CardTitle, CardDescription, CardContent and CardFooter sub-components.
CSS Grid handles this automatically: className='grid grid-cols-3 gap-4'. All cards in a row are equal height by default. For Flexbox: add h-full to each card inside a flex container.
Wrap the card in a button or add onClick directly: <Card onClick={handleClick} className='cursor-pointer hover:shadow-md transition-shadow'>. For navigation wrap in a Next.js Link or React Router Link.
Add the image above CardHeader: <Card><img src='' className='rounded-t-xl w-full h-48 object-cover' /><CardHeader>...</CardHeader></Card>. The rounded-t-xl matches the card's top border radius.

Need a Full React + Next.js Dashboard Template?

Get a complete React + Next.js dashboard with 50+ components — built by the same team behind BootstrapPlanet.

Browse Templates →

Use code FIRST30 for 30% off.

Related Components