Back to Dictionary
Action Feedback
●○○Ready to Use
Recommended default

Hover Lift Effect

A card or button smoothly translates upwards by a few pixels and increases its shadow cast, creating the illusion of moving closer to the user on hover.

Use

Interactive cards in a grid

Avoid

Dense data tables

Safer Alternative

No safer default listed.

Risk Level

Low risk

Live Demo

What It Is

A card or button smoothly translates upwards by a few pixels and increases its shadow cast, creating the illusion of moving closer to the user on hover.

When to Use

  • Interactive cards in a grid
  • Pricing tiers
  • Feature showcases on landing pages

When NOT to Use

  • Dense data tables
  • Inline text links

Configuration Tips

  • 01Lift by -4px or -6px (translate-y-[-4px])
  • 02Transition shadow from sm to md or lg
  • 03Use a 200-300ms ease-out timing function

You've Seen It In

StripeVercelLinear

AI Implementation Prompts

Move from a fast scaffold to production details, then tune timing and edge states.

Make this card lift up slightly and cast a bigger shadow when I hover over it.

Reference Implementation

The same implementation approach used by the live preview, kept compact enough to inspect and adapt.

'use client';
import { motion } from 'framer-motion';
import { useState, useEffect } from 'react';

export function HoverLiftEffectDemo({ isPlaying = false }: { isPlaying?: boolean }) {
    const [isHovered, setIsHovered] = useState(false);

    useEffect(() => {
        if (!isPlaying) {
            setIsHovered(false);
            return;
        }

        const interval = setInterval(() => {
            setIsHovered(true);
            setTimeout(() => setIsHovered(false), 1000);
        }, 2000);

        return () => clearInterval(interval);
    }, [isPlaying]);

    return (
        <div className="flex h-64 w-full items-center justify-center rounded-2xl bg-stone-50 p-6 shadow-sm ring-1 ring-stone-200 perspective-1000">
            <motion.div
                animate={isHovered ? { y: -8, boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.15)' } : { y: 0, boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' }}
                transition={{ duration: 0.3, ease: 'easeOut' }}
                className="flex w-48 flex-col gap-4 rounded-xl border border-stone-200 bg-white p-5 cursor-pointer"
                onMouseEnter={() => !isPlaying && setIsHovered(true)}
                onMouseLeave={() => !isPlaying && setIsHovered(false)}
            >
                <div className="h-10 w-10 rounded-full bg-stone-200" />
                <div className="h-4 w-3/4 rounded bg-stone-800" />
                <div className="h-3 w-1/2 rounded bg-stone-300" />
            </motion.div>
        </div>
    );
}