driftkit
Recipes/Stripe Card Hover

Stripe-Style Card Hover

The signature Stripe pricing card hover — lift, 3D tilt, and cursor glow that makes flat cards feel physical.

BeginnerCardGlow Card

Live Demo

Starter

$12/mo
  • 5 projects
  • 10GB storage
  • Email support

Pro

$29/mo
  • Unlimited projects
  • 100GB storage
  • Priority support
  • API access

Enterprise

$79/mo
  • Everything in Pro
  • 1TB storage
  • Dedicated account
  • SLA

How It Works

1.

Track cursor position — useMotionValue captures mouse X/Y relative to card center (-0.5 to 0.5)

2.

Transform to rotation — useTransform maps position to ±5° rotation on both axes

3.

Add spring smoothing — useSpring wraps the transform so tilt eases naturally (no jitter)

4.

Lift on hover — whileHover with spring transition creates the satisfying "pick up" feel

Code

import { motion, useMotionValue, useTransform, useSpring } from "framer-motion";

function StripeCard({ children }) {
  const x = useMotionValue(0);
  const y = useMotionValue(0);

  // Cursor position → rotation (max ±5°)
  const rotateX = useSpring(useTransform(y, [-0.5, 0.5], [5, -5]), {
    stiffness: 300, damping: 30,
  });
  const rotateY = useSpring(useTransform(x, [-0.5, 0.5], [-5, 5]), {
    stiffness: 300, damping: 30,
  });

  function handleMouseMove(e) {
    const rect = e.currentTarget.getBoundingClientRect();
    x.set((e.clientX - rect.left) / rect.width - 0.5);
    y.set((e.clientY - rect.top) / rect.height - 0.5);
  }

  return (
    <motion.div
      onMouseMove={handleMouseMove}
      onMouseLeave={() => { x.set(0); y.set(0); }}
      style={{ rotateX, rotateY, transformPerspective: 800 }}
      whileHover={{ y: -8, transition: { type: "spring", stiffness: 400, damping: 25 } }}
    >
      {children}
    </motion.div>
  );
}

Spring Tuning

// Why these spring values?
const tiltSpring = { stiffness: 300, damping: 30 };
// stiffness: 300 → responsive but not twitchy
// damping: 30 → smooth settle, no oscillation
// No mass specified → defaults to 1 (natural feel)

const liftSpring = { stiffness: 400, damping: 25 };
// stiffness: 400 → snappier for the lift (feels decisive)
// damping: 25 → slight overshoot on hover-in (playful)

Try it: increase stiffness to 600 for a snappier feel, or drop damping to 15 for more wobble. Use the Spring Playground to visualize.