UI/Components/Card elements/Card Flip

Card Flip

A Remotion video component that animates a card flipping in 3D space.

Clippkit
Card Flip?
0:00 / 0:04

Installation

CLI

npx shadcn@latest add "https://clippkit.com/r/card-flip"

Manual

Create a new file, for example, at src/components/clippkit/card-flip.tsx (or your preferred location) and paste the following code into it.

/**
 * Free Remotion Template Component
 * ---------------------------------
 * This template is free to use in your projects!
 * Credit appreciated but not required.
 *
 * Created by the team at https://www.reactvideoeditor.com
 *
 * Happy coding and building amazing videos! 🎉
 */
 
"use client";
 
import { spring, useCurrentFrame, useVideoConfig } from "remotion";
 
interface CardFlipProps {
  frontText?: string;
  backText?: string;
  frontTextColor?: string;
  backTextColor?: string;
  frontBackgroundColor?: string;
  backBackgroundColor?: string;
  fontSize?: string;
  width?: string;
  height?: string;
  borderRadius?: string;
  borderColor?: string;
  borderWidth?: string;
  borderStyle?: "solid" | "dashed" | "dotted";
  durationInFrames?: number;
  damping?: number;
  mass?: number;
  stiffness?: number;
  boxShadow?: string;
}
 
export function CardFlip({
  frontText = "Clippk.it",
  backText = "Remotion",
  frontTextColor = "var(--card-foreground)",
  backTextColor = "var(--card-foreground)",
  frontBackgroundColor = "var(--muted)",
  backBackgroundColor = "var(--card)",
  fontSize = "1.25rem",
  width = "200px",
  height = "280px",
  borderRadius = "15px",
  borderColor = "var(--ring)",
  borderWidth = "1px",
  borderStyle = "solid",
  durationInFrames = 70,
  damping = 18,
  mass = 0.5,
  stiffness = 100,
  boxShadow = `0 1px 3px var(--border), 0 6px 12px oklch(from var(--border) calc(l - 0.1) c h / 30%)`,
}: CardFlipProps) {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
 
  const rotation = spring({
    frame,
    fps,
    from: 0,
    to: 360,
    durationInFrames,
    config: {
      damping,
      mass,
      stiffness,
    },
  });
 
  const commonFaceStyle: React.CSSProperties = {
    position: "absolute",
    width: "100%",
    height: "100%",
    backfaceVisibility: "hidden",
    borderRadius,
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    fontSize,
    fontWeight: "bold",
    padding: "10px",
    boxSizing: "border-box",
    borderWidth,
    borderStyle,
  };
 
  return (
    <div
      style={{
        position: "absolute",
        top: "50%",
        left: "50%",
        perspective: "1200px",
        perspectiveOrigin: "50% 50%",
        transform: "translate(-50%, -50%)",
      }}
    >
      <div
        style={{
          width,
          height,
          transform: `rotateY(${rotation}deg)`,
          transformStyle: "preserve-3d",
          position: "relative",
          boxShadow,
          borderRadius,
        }}
      >
        <div
          style={{
            ...commonFaceStyle,
            background: frontBackgroundColor,
            color: frontTextColor,
            borderColor: borderColor,
          }}
        >
          {frontText}
        </div>
        <div
          style={{
            ...commonFaceStyle,
            background: backBackgroundColor,
            color: backTextColor,
            borderColor: borderColor,
            transform: "rotateY(180deg)",
          }}
        >
          {backText}
        </div>
      </div>
    </div>
  );
}
Update the import paths in your Remotion compositions if you placed the file in a different location than shown in the usage examples.

Usage

Once the CardFlip component is added to your project (either via CLI or Manually), you can integrate it into your Remotion project by importing it and defining a Composition.

Prerequisite

Ensure you have a Remotion project set up. If not, please refer to the Remotion documentation to get started.

Project Structure Example

Here’s an example folder layout showing where to place the component and how it fits into a typical Remotion project

app/main.tsx
import { Player } from "@remotion/player";
 
import CardFlip from "../components/card-flip";
 
export function CardFlipDemo() {
  const cardFlipProps = {
    frontText: "Clippkit",
    backText: "Card Flip?",
    frontTextColor: "var(--foreground)",
    backTextColor: "var(--foreground)",
    frontBackgroundColor: "var(--card)",
    backBackgroundColor: "var(--card)",
    fontSize: "1.3rem",
    width: "220px",
    height: "300px",
    borderRadius: "18px",
    borderColor: "var(--primary)",
    borderWidth: "1px",
    borderStyle: "solid" as const,
    durationInFrames: 80,
    damping: 18,
    mass: 0.6,
    stiffness: 90,
  };
 
  return (
    <Player
      component={CardFlip}
      inputProps={cardFlipProps}
      durationInFrames={120}
      compositionWidth={480}
      compositionHeight={400}
      fps={30}
      style={{
        width: "100%",
        height: "100%",
        backgroundColor: "var(--background)",
      }}
      autoPlay
      controls
      loop
    />
  );
}

Define a Composition

In your Remotion project's entry file (commonly src/Root.tsx, src/index.tsx, app/main.tsx), import CardFlip and define a Composition.

app/main.tsx (or equivalent)
import { Player } from "@remotion/player";

import CardFlip from "@/components/clippkit/card-flip"; // Assuming you placed it in src/components/clippkit

export default function CardFlipScene() {
  const cardFlipProps = {
    frontText: "Hello From Remotion!",
    backText: "Card Back!",
    frontTextColor: "#FFF",
    backTextColor: "#FFF",
    frontBackgroundColor: "linear-gradient(45deg, #7e22ce, #a21caf)",
    backBackgroundColor: "linear-gradient(45deg, #166534, #15803d)",
    fontSize: "1.8rem",
    width: "320px",
    height: "420px",
    borderRadius: "25px",
    durationInFrames: 90,
    damping: 18,
    mass: 0.6,
    stiffness: 90,
  };

  return (
    <Player
      component={CardFlip}
      inputProps={cardFlipProps}
      durationInFrames={120} // Total duration of the player timeline
      compositionWidth={500}
      compositionHeight={500} // Square aspect ratio to see the card flip nicely
      fps={30}
      style={{
        width: "100%",
        height: "100%",
      }}
      autoPlay
      controls
      loop
    />
  );
}

API Reference

The component exported as CardFlip (e.g., from apps/docs/registry/default/ui/card-flip.tsx or your project's component path) accepts the following props to customize its animation and appearance:

PropTypeDefault ValueDescription
frontTextstring"Remotion 👋"The text content to display on the front of the card.
backTextstring"Back"The text content to display on the back of the card.
frontTextColorstring"white"The color of the text on the front of the card. Accepts any valid CSS color value.
backTextColorstring"white"The color of the text on the back of the card. Accepts any valid CSS color value.
frontBackgroundColorstring"linear-gradient(45deg, #1e3a8a, #3b82f6)"The background of the front of the card. Accepts any valid CSS background value.
backBackgroundColorstring"linear-gradient(45deg, #1e3a8a, #3b82f6)"The background of the back of the card. Accepts any valid CSS background value.
fontSizestring"2rem"The font size of the text on both sides of the card. Accepts any valid CSS font-size value.
widthstring"300px"The width of the card. Accepts any valid CSS width value.
heightstring"400px"The height of the card. Accepts any valid CSS height value.
borderRadiusstring"20px"The border radius of the card. Accepts any valid CSS border-radius value.
durationInFramesnumber60The duration of the flip animation in frames.
dampingnumber15The damping amount for the spring animation. Controls how quickly oscillations die down.
massnumber0.5The mass for the spring animation.
stiffnessnumber100The stiffness for the spring animation.

On this page