NEW
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
shadcn registry is live·
Learn more
Skip to content
Docs

Flipping cards

A list of flip cards arranged, each card representing an item or concept. Hovering on a card flips it to reveal additional details.

requires interactionhover
Loading...

Installation

CLI

pnpm dlx shadcn@latest add https://animata.design/r/list/flipping-cards.json

Manual

Install dependencies

This uses Marquee for the text. Install it by following the instructions here.

npm install motion

Run the following command

It will create a new file called flipping-cards.tsx inside the components/animata/list directory.

mkdir -p components/animata/list && touch components/animata/list/flipping-cards.tsx

Paste the code

Open the newly created file and paste the following code:

import { PlusCircle } from "lucide-react";
 
import Marquee from "@/animata/container/marquee";
import { cn } from "@/lib/utils";
 
interface CardProps {
  show: React.ReactNode;
  reveal: React.ReactNode;
}
 
interface CardDetailsProps extends React.HTMLAttributes<HTMLDivElement> {
  title: string;
  font: string;
  image: string;
  index?: number;
}
 
interface FlippingCardProps {
  list: CardDetailsProps[];
}
 
const Card = ({ show, reveal }: CardProps) => {
  const common = "absolute flex w-full h-full  [backface-visibility:hidden]";
  return (
    <div className={cn("group/flip h-60 w-48 [perspective:1000px]")}>
      <div
        className={cn(
          "relative h-full transition delay-75 duration-500 ease-linear [transform-style:preserve-3d] group-hover/flip:[transform:rotateY(-180deg)]",
        )}
      >
        <div className={cn("bg-white", common)}>{show}</div>
        <div
          className={cn("[transform:rotateY(180deg)]", common)}
          style={{
            // Note: Set your own color over here
            backgroundColor: `#${(((1 << 24) * Math.random()) | 0).toString(16).padStart(6, "0")}`,
          }}
        >
          {reveal}
        </div>
      </div>
    </div>
  );
};
 
const CardDetails = ({ title, image, font, index }: CardDetailsProps) => {
  return (
    <Card
      show={
        <div className="flex w-full flex-col border-[1px] border-black/15 px-3 py-4 text-sm">
          <span className="border-t-2 border-black text-black pt-1">{font}</span>
 
          <span className="mt-4 border-b-2 border-black text-black px-1 font-serif text-8xl">
            {title}
          </span>
          <div className="mt-12 flex items-center justify-between">
            <span>{(index ?? 0) + 1}</span>
            <PlusCircle size={18} />
          </div>
        </div>
      }
      reveal={
        <div className="flex w-full flex-col justify-between overflow-hidden py-4 text-sm">
          <img alt="" src={image} className="size-32 px-2" />
          <Marquee className="font-serif text-5xl text-white" applyMask={false}>
            {font.split(" ")[0]}
          </Marquee>
          <div className="flex items-center justify-between px-3">
            <span className="text-black">See more</span>
            <PlusCircle size={18} color="black" />
          </div>
        </div>
      }
    />
  );
};
 
export default function FlippingCard({ list }: FlippingCardProps) {
  return (
    <div className="grid grid-cols-3 gap-5 max-sm:grid-cols-2">
      {list.map((item, index) => (
        <CardDetails
          key={`card_${index}`}
          index={index}
          title={item.title}
          font={item.font}
          image={item.image}
        />
      ))}
    </div>
  );
}

Credits

Built by Bibek Bhattarai