How do you animate cards without hurting usability?

Card effects make grouped content such as products, articles or team members feel tangible. They combine CSS transforms for tilt and lift, backface-visibility for flip cards, backdrop-filter for glass surfaces, and CSS Grid with container queries for Bento layouts that adapt to their own width rather than the viewport.

How to choose, performance and accessibility
  • Use a subtle Hover Lift or 3D Tilt Effect on clickable product cards, Flip Card when the back holds useful detail, and Stacked Cards or Card Morph for storytelling sections.
  • Make the whole card one link or button, keep text readable during motion, and reduce the tilt for prefers-reduced-motion.
  • 3D Tilt Effect, Glassmorphism, Basic Bento, Holo Tilt & Glare, Foil Shimmer and Page Curl Reveal are free with their code; the other cards come with Premium.
3D Tilt

3D Tilt Effect

The card tilts based on the mouse position.

JS 3D Interactive
Effect page →
View source code
HTML
<div class="card-demo card-tilt" id="tiltCard">
  <span class="tilt-content">3D Tilt</span>
</div>
CSS
.card-demo  {
   width: 280px;
   height: 180px;
   background: var(--bg-card);
   border-radius: var(--radius-xl);
   display: flex;
   align-items: center;
   justify-content: center;
   font-weight: 600;
   position: relative;
   cursor: pointer;
   }

.card-tilt  {
   transform-style: preserve-3d;
   transition: transform 0.1s;
   }

.card-tilt:hover  {
   box-shadow: rgba(99, 102, 241, 0.3) 0px 25px 50px;
   }

.card-tilt .tilt-content  {
   transform: translateZ(30px);
   }

/* Variables du design system du site, dont ce code depend. Sans elles,
   l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
   Valeurs reprises de css/style.css — a adapter librement. */
.card-demo, .card-tilt {
  --bg-card: #12121a;
  --radius-xl: 1rem;
}

/* Le fond de carte est desormais sombre : sans couleur de texte declaree,
   le libelle heritait du noir de la page hote et devenait illisible (revue Owen). */
.card-demo { color: #fff; }
JavaScript
(function(){
    // 3D Tilt Effect
    const tiltCard = document.getElementById('tiltCard');
    if (tiltCard) {
      tiltCard.addEventListener('mousemove', (e) => {
        const rect = tiltCard.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        const centerX = rect.width / 2;
        const centerY = rect.height / 2;
        const rotateX = (y - centerY) / 10;
        const rotateY = (centerX - x) / 10;
        tiltCard.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
      });
      tiltCard.addEventListener('mouseleave', () => {
        tiltCard.style.transform = 'perspective(1000px) rotateX(0) rotateY(0)';
      });
    }

    // Spotlight Effect
    const spotlightCard = document.getElementById('spotlightCard');
    if (spotlightCard) {
      spotlightCard.addEventListener('mousemove', (e) => {
        const rect = spotlightCard.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        spotlightCard.style.setProperty('--spotlight-x', x + 'px');
        spotlightCard.style.setProperty('--spotlight-y', y + 'px');
      });
    }

    // Card Morph Expand Effect
    const morphExpandCard = document.getElementById('morphExpandCard');
    if (morphExpandCard) {
      morphExpandCard.addEventListener('click', () => {
        morphExpandCard.classList.toggle('expanded');
      });
      // Close when clicking outside
      document.addEventListener('click', (e) => {
        if (!morphExpandCard.contains(e.target) && morphExpandCard.classList.contains('expanded')) {
          morphExpandCard.classList.remove('expanded');
        }
      });
    }
  })();
Glass

Glassmorphism

Frosted glass effect with backdrop-filter blur.

CSS Glass Modern
Effect page →
View source code
HTML
<div class="glass-bg" style="width:100%;min-height:300px;">
  <div class="card-demo card-glass">
    Glass
  </div>
</div>
CSS
.card-demo  {
   width: 280px;
   height: 180px;
   background: var(--bg-card);
   border-radius: var(--radius-xl);
   display: flex;
   align-items: center;
   justify-content: center;
   font-weight: 600;
   position: relative;
   cursor: pointer;
   }

.card-glass  {
   background: rgba(255, 255, 255, 0.05);
   backdrop-filter: blur(20px);
   border: 1px solid rgba(255, 255, 255, 0.1);
   box-shadow: rgba(0, 0, 0, 0.3) 0px 8px 32px;
   }

.card-glass::before  {
   content: "";
   position: absolute;
   inset: 0px;
   background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 50%);
   border-radius: inherit;
   pointer-events: none;
   }

.glass-bg  {
   background: linear-gradient(135deg, rgb(102, 126, 234) 0%, rgb(118, 75, 162) 50%, rgb(240, 147, 251) 100%);
   }

/* Variables du design system du site, dont ce code depend. Sans elles,
   l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
   Valeurs reprises de css/style.css — a adapter librement. */
.glass-bg {
  --bg-card: #12121a;
  --radius-xl: 1rem;
}
JavaScript
/* Pure CSS — no JavaScript required */

Spotlight Effect

Light that follows the cursor across the card.

JS Light Hover

Animated Border

Continuously animated gradient border.

CSS Gradient Loop

Flip Card

3D flip on hover.

CSS 3D Flip

Hover Lift

Lift and scale on hover with drop shadow.

CSS Hover Shadow

Morphing Shape

Border-radius that changes continuously.

CSS Animation Organic

Glow Pulse

Glowing halo that pulses continuously.

CSS Glow Loop

Stacked Cards

Cards fan out on hover.

CSS Stack Hover

Card Morph

The card expands and reveals its content on click.

JS Click Expand

Parallax Layers

Depth effect with multiple 3D layers.

CSS 3D Parallax

Shine Effect

Shiny reflection that sweeps across the card on hover.

CSS Hover Light

Neumorphic

Soft UI style with gentle shadows and subtle reliefs.

CSS Soft UI Modern

Claymorphism

3D clay style with organic depth effect.

CSS 3D Organic

Content Reveal

Hidden content progressively reveals on hover.

CSS Hover Reveal

Image Zoom

The image zooms in within the card on hover.

CSS Hover Image

Holographic

Continuously animated rainbow holographic effect.

CSS Rainbow Loop
Featured
A
B
Wide
C
D

Basic Bento

Simple bento grid with hover animations on each cell. Scale and glow effect.

CSS Grid Hover
Effect page →
View source code
HTML
<div class="bento-container">
  <div class="bento-grid bento-basic">
    <div class="bento-cell cell-1">Featured</div>
    <div class="bento-cell cell-2">A</div>
    <div class="bento-cell cell-3">B</div>
    <div class="bento-cell cell-4">Wide</div>
    <div class="bento-cell cell-5">C</div>
    <div class="bento-cell cell-6">D</div>
  </div>
</div>
CSS
.bento-container  {
   width: 100%;
   max-width: 600px;
   aspect-ratio: 4 / 3;
   }

.bento-grid  {
   display: grid;
   gap: 12px;
   width: 100%;
   height: 100%;
   }

.bento-cell  {
   background: var(--bg-card);
   border-radius: var(--radius-lg);
   border: 1px solid var(--border);
   display: flex;
   align-items: center;
   justify-content: center;
   font-weight: 600;
   font-size: 0.85rem;
   color: var(--text-secondary);
   position: relative;
   overflow: hidden;
   }

.bento-basic  {
   grid-template-columns: repeat(4, 1fr);
   grid-template-rows: repeat(3, 1fr);
   }

.bento-basic .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-basic .cell-2  {
   grid-column: span 1;
   }

.bento-basic .cell-3  {
   grid-column: span 1;
   }

.bento-basic .cell-4  {
   grid-column: span 2;
   }

.bento-basic .cell-5  {
   grid-column: span 2;
   }

.bento-basic .cell-6  {
   grid-column: span 2;
   }

.bento-basic .bento-cell  {
   transition: 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
   }

.bento-basic .bento-cell:hover  {
   transform: scale(1.05);
   z-index: 10;
   border-color: rgba(99, 102, 241, 0.5);
   box-shadow: rgba(99, 102, 241, 0.3) 0px 20px 40px;
   }

.bento-basic .bento-cell::before  {
   content: "";
   position: absolute;
   inset: 0px;
   background: linear-gradient(135deg, rgba(99, 102, 241, 0.1) 0%, transparent 50%);
   opacity: 0;
   transition: opacity 0.3s;
   }

.bento-basic .bento-cell:hover::before  {
   opacity: 1;
   }

.bento-images .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-images .cell-2  {
   grid-column: span 2;
   }

.bento-images .cell-3  {
   grid-area: span 2 / span 1;
   }

.bento-images .cell-4  {
   grid-column: span 1;
   }

.bento-images .cell-5  {
   grid-column: span 2;
   }

.bento-images .cell-6  {
   grid-column: span 1;
   }

.bento-images .bento-cell  {
   background-size: cover;
   background-position: center center;
   cursor: pointer;
   }

.bento-images .cell-1  {
   background: linear-gradient(135deg, rgb(102, 126, 234) 0%, rgb(118, 75, 162) 100%);
   }

.bento-images .cell-2  {
   background: linear-gradient(135deg, rgb(240, 147, 251) 0%, rgb(245, 87, 108) 100%);
   }

.bento-images .cell-3  {
   background: linear-gradient(135deg, rgb(79, 172, 254) 0%, rgb(0, 242, 254) 100%);
   }

.bento-images .cell-4  {
   background: linear-gradient(135deg, rgb(67, 233, 123) 0%, rgb(56, 249, 215) 100%);
   }

.bento-images .cell-5  {
   background: linear-gradient(135deg, rgb(250, 112, 154) 0%, rgb(254, 225, 64) 100%);
   }

.bento-images .cell-6  {
   background: linear-gradient(135deg, rgb(161, 140, 209) 0%, rgb(251, 194, 235) 100%);
   }

.bento-images .bento-cell .overlay  {
   position: absolute;
   inset: 0px;
   background: rgba(0, 0, 0, 0.4);
   display: flex;
   align-items: center;
   justify-content: center;
   opacity: 0;
   transition: 0.4s;
   }

.bento-images .bento-cell .overlay span  {
   color: white;
   font-weight: 700;
   font-size: 1rem;
   transform: translateY(20px);
   transition: transform 0.4s;
   }

.bento-images .bento-cell:hover .overlay  {
   opacity: 1;
   }

.bento-images .bento-cell:hover .overlay span  {
   transform: translateY(0px);
   }

.bento-animated .cell-1  {
   grid-area: span 1 / span 2;
   }

.bento-animated .cell-2  {
   grid-area: span 2 / span 1;
   }

.bento-animated .cell-3  {
   grid-area: span 2 / span 1;
   }

.bento-animated .cell-4  {
   grid-column: span 2;
   }

.bento-animated .cell-5  {
   grid-area: span 1 / span 2;
   }

.bento-animated .cell-6  {
   grid-area: span 1 / span 2;
   }

.bento-animated .bento-cell  {
   opacity: 0;
   transform: translateY(30px) scale(0.9);
   animation: 0.6s cubic-bezier(0.16, 1, 0.3, 1) 0s 1 normal forwards running bentoFadeIn;
   }

.bento-animated .cell-1  {
   animation-delay: 0.1s;
   background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
   }

.bento-animated .cell-2  {
   animation-delay: 0.2s;
   background: linear-gradient(135deg, rgb(236, 72, 153) 0%, rgb(244, 63, 94) 100%);
   }

.bento-animated .cell-3  {
   animation-delay: 0.3s;
   background: linear-gradient(135deg, rgb(6, 182, 212) 0%, rgb(59, 130, 246) 100%);
   }

.bento-animated .cell-4  {
   animation-delay: 0.4s;
   background: linear-gradient(135deg, rgb(16, 185, 129) 0%, rgb(5, 150, 105) 100%);
   }

.bento-animated .cell-5  {
   animation-delay: 0.5s;
   background: linear-gradient(135deg, rgb(245, 158, 11) 0%, rgb(239, 68, 68) 100%);
   }

.bento-animated .cell-6  {
   animation-delay: 0.6s;
   background: linear-gradient(135deg, rgb(139, 92, 246) 0%, rgb(217, 70, 239) 100%);
   }

.bento-animated .bento-cell span  {
   color: white;
   font-weight: 700;
   }

.bento-interactive .bento-cell  {
   cursor: pointer;
   transition: 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
   background: var(--bg-elevated);
   }

.bento-interactive .bento-cell.expanded  {
   z-index: 100;
   background: linear-gradient(135deg, rgb(99, 102, 241) 0%, rgb(139, 92, 246) 100%);
   box-shadow: rgba(99, 102, 241, 0.4) 0px 25px 50px;
   grid-area: span 2 / span 2 !important;
   }

.bento-interactive .bento-cell .expand-icon  {
   width: 30px;
   height: 30px;
   border-radius: 50%;
   background: rgba(99, 102, 241, 0.2);
   display: flex;
   align-items: center;
   justify-content: center;
   transition: 0.3s;
   }

.bento-interactive .bento-cell:hover .expand-icon  {
   background: rgba(99, 102, 241, 0.4);
   transform: scale(1.1);
   }

.bento-interactive .bento-cell.expanded .expand-icon  {
   background: rgba(255, 255, 255, 0.2);
   }

.bento-interactive .bento-cell.expanded .cell-content span  {
   color: white;
   }

.bento-stats .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-stats .cell-2  {
   grid-column: span 2;
   }

.bento-stats .cell-3  {
   grid-column: span 1;
   }

.bento-stats .cell-4  {
   grid-column: span 1;
   }

.bento-stats .cell-5  {
   grid-column: span 2;
   }

.bento-stats .cell-6  {
   grid-column: span 2;
   }

.bento-stats .bento-cell  {
   flex-direction: column;
   gap: 8px;
   padding: 16px;
   }

.bento-stats .cell-1 .stat-number  {
   font-size: 3rem;
   }

.bento-stats .bento-cell:hover .stat-bar-fill  {
   width: var(--fill-width, 75%);
   }

.bento-reveal .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-reveal .cell-2  {
   grid-area: span 1 / span 2;
   }

.bento-reveal .cell-3  {
   grid-column: span 2;
   }

.bento-reveal .cell-4  {
   grid-area: span 1 / span 2;
   }

.bento-reveal .cell-5  {
   grid-column: span 2;
   }

.bento-reveal .bento-cell  {
   cursor: pointer;
   background: var(--bg-elevated);
   }

.bento-reveal .bento-cell:hover .reveal-front  {
   opacity: 0;
   transform: scale(1.2);
   }

.bento-reveal .bento-cell:hover .reveal-back  {
   opacity: 1;
   transform: scale(1);
   }

.bento-reveal .bento-cell:hover  {
   border-color: rgba(99, 102, 241, 0.3);
   box-shadow: rgba(99, 102, 241, 0.2) 0px 10px 30px;
   }

.bento-cardstack .cell-1  {
   grid-area: span 2 / span 2;
   }

.bento-cardstack .cell-2  {
   grid-area: span 2 / span 2;
   }

.bento-cardstack .cell-3  {
   grid-column: span 2;
   }

.bento-cardstack .cell-4  {
   grid-column: span 2;
   }

.bento-cardstack .bento-cell  {
   padding: 16px;
   background: var(--bg-elevated);
   }

.bento-cardstack .bento-cell:hover .stacked-card:nth-child(1)  {
   transform: translate(-50%, -50%) translateX(-30%) rotate(-10deg);
   }

.bento-cardstack .bento-cell:hover .stacked-card:nth-child(2)  {
   transform: translate(-50%, -50%) translateY(-5px);
   }

.bento-cardstack .bento-cell:hover .stacked-card:nth-child(3)  {
   transform: translate(-50%, -50%) translateX(30%) rotate(10deg);
   }

.bento-cardstack .bento-cell:hover .mini-card:nth-child(1)  {
   transform: translateY(-10px) rotate(-5deg);
   }

.bento-cardstack .bento-cell:hover .mini-card:nth-child(2)  {
   transform: translateY(-15px);
   }

.bento-cardstack .bento-cell:hover .mini-card:nth-child(3)  {
   transform: translateY(-10px) rotate(5deg);
   }

.bento-responsive .bento-cell  {
   transition: 0.5s cubic-bezier(0.16, 1, 0.3, 1);
   }

.bento-responsive .bento-cell span  {
   color: white;
   font-weight: 600;
   font-size: 0.7rem;
   }

.bento-responsive .bento-cell:hover  {
   transform: scale(1.05);
   z-index: 10;
   box-shadow: rgba(0, 0, 0, 0.3) 0px 15px 30px;
   }

@keyframes bentoFadeIn  {
   
  100%  {
   opacity: 1;
   transform: translateY(0px) scale(1);
   }
}

/* Variables du design system du site, dont ce code depend. Sans elles,
   l'acheteur obtenait des coins carres et des couleurs par defaut (revue Owen).
   Valeurs reprises de css/style.css — a adapter librement. */
.bento-container {
  --bg-card: #12121a;
  --bg-elevated: #1a1a24;
  --border: rgba(255, 255, 255, 0.08);
  --radius-lg: 0.75rem;
  --text-secondary: #a1a1aa;
}
JavaScript
/* Pure CSS — no JavaScript required */

Bento with Images

Cells with gradient backgrounds and overlay that appears on hover.

CSS Images Overlay

Animated Bento

Cells appear in cascade with a stagger effect on load.

CSS Animation Stagger

Interactive Bento

Click a cell to expand it. Click again to collapse it.

JS Click Expand

Bento with Stats

Statistics display with animated number counters on hover.

JS Stats Counter

Hover Reveal Bento

Content reveals on hover with a smooth transition.

CSS Reveal Hover

Bento Card Stack

Stacked cards that fan out on hover.

CSS Stack Cards

Responsive Bento

Grid that elegantly reorganizes. Resize the container to see the effect.

CSS Responsive Auto-fit

Grid to List Toggle

Items morphing between grid and list layout with smooth CSS grid transitions.

CSS Grid FLIP

Card Expand to Full

Card that expands from its position to full screen with position/size transition.

CSS JS FLIP

Tab Content Morph

Tab panel with morphing crossfade and content position transition.

CSS JS Tabs

Masonry to Grid

Items that animate from an organic masonry layout to a strict grid and back.

CSS Layout Transition

Sidebar to Overlay

Sidebar that transforms into a full-screen overlay with smooth content reflow.

CSS JS Layout

Split Screen Morph

Two-panel layout morphing between 50/50, 70/30, and single panel with CSS flex transitions.

CSS Flex Layout

Stacked to Spread

Stacked cards that spread into a grid with elastic cubic-bezier animation.

CSS Transform Elastic

Holographic Card 3D

Iridescent holographic card on hover, premium trading-card style. conic-gradient + blend modes + 3D transform. Zero JavaScript.

CSS pur 3D Premium

Shape-Aware Shadows

Shadows, borders and outlines that hug non-rectangular shapes with border-shape: pointed tag, notched ticket, chat bubble. Automatic drop-shadow fallback on every browser.

💡 Perfect for: promo badges, event tickets, chat bubbles, pointed tooltips, pricing cards.

CSS border-shape Cutting-edge Premium
GOLD MEMBER A. Dubois MBR‑2026‑0042

Holo Tilt & Glare

Pointer-driven holographic card: 3D tilt (rAF + lerp), iridescent glare tracking the cursor and a foil layer in inverse parallax — the depth of a real holo card. Elastic return on leave, reduced-motion fallback.

💡 Ideal for: premium loyalty cards, player badges, invitations, collectibles.

JS Pointer 3D Holographic
Effect page →
View source code
HTML
<div class="htg-wrap" tabindex="0" aria-label="Holographic card that follows the pointer">
  <div class="htg-card">
    <span class="htg-glare" aria-hidden="true">
    </span>
    <span class="htg-foil" aria-hidden="true">
    </span>
    <span class="htg-content">
      <span class="htg-badge">GOLD MEMBER</span>
      <strong class="htg-name">A. Dubois</strong>
      <span class="htg-num">MBR‑2026‑0042</span>
    </span>
  </div>
</div>
CSS
.htg-wrap  {
   perspective: 900px;
   display: inline-block;
   border-radius: 16px;
   }

.htg-wrap:focus-visible  {
   outline: rgb(168, 85, 247) solid 2px;
   outline-offset: 6px;
   }

.htg-card  {
   position: relative;
   width: 250px;
   height: 156px;
   border-radius: 14px;
   overflow: hidden;
   background: radial-gradient(120% 160% at var(--htg-mx, 70%) var(--htg-my, 20%), rgba(255,255,255,.16), transparent 55%),
                conic-gradient(from 230deg at 40% 30%, #1c1440, #232e63, #14324d, #3a1c55, #1c1440);
   transform: rotateX(var(--htg-ry, 0deg)) rotateY(var(--htg-rx, 0deg));
   box-shadow: rgba(0, 0, 0, 0.5) 0px 18px 40px;
   transform-style: preserve-3d;
   will-change: transform;
   }

.htg-glare  {
   position: absolute;
   inset: 0px;
   pointer-events: none;
   background: conic-gradient(from 0deg at var(--htg-mx, 70%) var(--htg-my, 25%),
                rgba(98,230,255,.5), rgba(255,138,225,.45), rgba(255,233,92,.4), rgba(177,140,255,.45), rgba(125,255,196,.4), rgba(98,230,255,.5));
   mix-blend-mode: screen;
   opacity: 0.62;
   filter: blur(6px);
   }

.htg-foil  {
   position: absolute;
   inset: -30%;
   pointer-events: none;
   background: repeating-linear-gradient(104deg, rgba(255, 255, 255, 0.09) 0px, rgba(255, 255, 255, 0.09) 1px, transparent 1px, transparent 3px, rgba(255, 255, 255, 0.043) 3px, rgba(255, 255, 255, 0.043) 4px, transparent 4px, transparent 7px);
   mix-blend-mode: color-dodge;
   transform: translate(var(--htg-fx, 0px), var(--htg-fy, 0px));
   }

.htg-content  {
   position: absolute;
   inset: 0px;
   padding: 16px 18px;
   display: flex;
   flex-direction: column;
   justify-content: flex-end;
   gap: 3px;
   transform: translateZ(24px);
   text-shadow: rgba(0, 0, 0, 0.65) 0px 1px 3px;
   }

.htg-badge  {
   align-self: flex-start;
   font-size: 0.58rem;
   font-weight: 800;
   letter-spacing: 0.16em;
   color: rgb(125, 255, 196);
   border: 1px solid rgba(125, 255, 196, 0.45);
   border-radius: 20px;
   padding: 3px 9px;
   margin-bottom: auto;
   }

.htg-name  {
   font-size: 1.05rem;
   color: rgb(255, 255, 255);
   }

.htg-num  {
   font-size: 0.7rem;
   letter-spacing: 0.18em;
   color: rgba(255, 255, 255, 0.75);
   }
JavaScript
(function() {
  /* fx-0821 — Holo Tilt & Glare : tilt + glare + foil pilotés au pointeur (rAF + lerp) */
  function initHtg() {
    if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
    document.querySelectorAll('.htg-wrap').forEach(function(wrap) {
      var card = wrap.querySelector('.htg-card');
      if (!card) return;
      var tx = 0, ty = 0, tmx = 70, tmy = 25, x = 0, y = 0, mx = 70, my = 25, raf = null;
      function loop() {
        x += (tx - x) * 0.12; y += (ty - y) * 0.12; mx += (tmx - mx) * 0.12; my += (tmy - my) * 0.12;
        card.style.setProperty('--htg-rx', x.toFixed(2) + 'deg');
        card.style.setProperty('--htg-ry', y.toFixed(2) + 'deg');
        card.style.setProperty('--htg-mx', mx.toFixed(1) + '%');
        card.style.setProperty('--htg-my', my.toFixed(1) + '%');
        card.style.setProperty('--htg-fx', (-(mx - 50) * 0.5).toFixed(1) + 'px');
        card.style.setProperty('--htg-fy', (-(my - 50) * 0.4).toFixed(1) + 'px');
        if (Math.abs(tx - x) > 0.05 || Math.abs(ty - y) > 0.05 || Math.abs(tmx - mx) > 0.2) raf = requestAnimationFrame(loop);
        else raf = null;
      }
      function kick() { if (!raf) raf = requestAnimationFrame(loop); }
      wrap.addEventListener('pointermove', function(e) {
        var r = card.getBoundingClientRect();
        var px = (e.clientX - r.left) / r.width, py = (e.clientY - r.top) / r.height;
        tx = (px - 0.5) * 22; ty = -(py - 0.5) * 18; tmx = px * 100; tmy = py * 100; kick();
      });
      wrap.addEventListener('pointerleave', function() { tx = 0; ty = 0; tmx = 70; tmy = 25; kick(); });
    });
  }
  if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', initHtg);
  else initHtg();
})();
FOIL ✦ PRO

Foil Shimmer

Stamped holographic foil in pure CSS: three text-clipped layers — animated iridescent gradient, metal grain, specular sweep. Foil-border pill variant included. Hover speeds up the shimmer.

💡 Ideal for: premium badges, pricing card headlines, limited-edition labels.

CSS Typography Hover Holographic
Effect page →
View source code
HTML
<div class="fsh-demo">
  <span class="fsh-foil">
    <span class="fsh-text fsh-big">FOIL</span>
  </span>
  <span class="fsh-pill">
    <span class="fsh-inner">
      <span class="fsh-foil">
        <span class="fsh-text">✦&nbsp;PRO</span>
      </span>
    </span>
  </span>
</div>
CSS
.fsh-demo  {
   display: flex;
   flex-direction: column;
   align-items: center;
   gap: 18px;
   }

.fsh-foil  {
   display: inline-block;
   }

.fsh-text  {
   background-image: linear-gradient(108deg, transparent 30%, rgba(255, 255, 255, 0.5) 47%, rgba(255, 255, 255, 0.95) 50%, rgba(255, 255, 255, 0.5) 53%, transparent 70%), repeating-linear-gradient(104deg, rgba(255, 255, 255, 0.07) 0px, rgba(255, 255, 255, 0.07) 1px, transparent 1px, transparent 3px, rgba(200, 175, 90, 0.04) 3px, rgba(200, 175, 90, 0.04) 4px, transparent 4px, transparent 6px), linear-gradient(135deg, rgb(255, 215, 0) 0%, rgb(255, 192, 203) 18%, rgb(232, 234, 240) 36%, rgb(0, 229, 255) 54%, rgb(199, 125, 255) 72%, rgb(232, 234, 240) 84%, rgb(255, 215, 0) 100%);
   background-size: 350% 100%, auto, 300% 100%;
   background-position: -120% 0px, 0px 0px, 0% 50%;
   background-blend-mode: screen, overlay, normal;
   background-clip: text;
   -webkit-text-fill-color: transparent;
   color: transparent;
   display: inline-block;
   font-weight: 900;
   animation: fsh-pan var(--fsh-speed, 3.2s) linear infinite;
   }

.fsh-big  {
   font-size: 3.2rem;
   letter-spacing: 0.04em;
   }

.fsh-foil:hover .fsh-text  {
   --fsh-speed: .7s;
   }

.fsh-pill  {
   display: inline-block;
   padding: 2px;
   border-radius: 20px;
   background: linear-gradient(135deg, rgb(255, 215, 0), rgb(255, 192, 203) 25%, rgb(0, 229, 255) 55%, rgb(199, 125, 255) 80%, rgb(255, 215, 0)) 0% 0% / 300% 100%;
   animation: 3.2s linear 0s infinite normal none running fsh-pan-border;
   }

@keyframes fsh-pan  {
   
  0%  {
   background-position: -120% 0px, 0px 0px, 0% 50%;
   }
  40%  {
   background-position: -120% 0px, 0px 0px, 120% 50%;
   }
  65%  {
   background-position: 270% 0px, 0px 0px, 195% 50%;
   }
  100%  {
   background-position: 270% 0px, 0px 0px, 300% 50%;
   }
}

@keyframes fsh-pan-border  {
   
  100%  {
   background-position: 300% 50%;
   }
}

.fsh-inner  {
   display: inline-block;
   background: rgb(16, 16, 24);
   border-radius: 18px;
   padding: 6px 14px;
   }

.fsh-pill .fsh-text  {
   font-size: 0.85rem;
   letter-spacing: 0.1em;
   }
JavaScript
/* Pure CSS — no JavaScript required */

Holographic Sticker Peel

Die-cut holographic sticker that peels off: hover lifts the corner, click peels it three-quarters away. The back exposes grey glue and inverted iridescence — two interpolated clip-paths, growing shadow, glue-stretch.

💡 Ideal for: e-commerce promo stickers, “new” badges, event tags.

CSS clip-path Click Premium

Prismatic Refraction Card

Chromatic-dispersion glass: the edges split light into red/cyan fringes while a rainbow band sweeps the surface following the cursor. rAF + lerp 3D tilt, saturated backdrop-filter, scrim-guaranteed readability.

💡 Ideal for: premium pricing cards, landing heroes, featured-capability widgets.

CSS backdrop-filter Pointer Premium

Holo Pack Opening

TCG-Pocket-style booster opening: a spark cuts the top of the wrapper along a glowing line, the strip tears away and flutters off, and the cards slide out through the opening in cascade. Then inspection — auto zoom, click to flip (3D flip with a real back), ‹ › and keyboard navigation. 1 to N cards, replayable (fresh pack), zero dependencies.

💡 Ideal for: reward reveals, gift cards, loot boxes, gamified onboarding.

JS clip-path Sequence Premium

Page Curl Reveal

Hover: the corner curls like a real page. Click: it peels away entirely to reveal the hidden content, click again to lay it back. Animated gradient fold, shadow and clip-path, accessible toggle.

💡 Perfect for: revealing a promo code, a surprise, a card back, a content teaser.

CSS clip-path Hover
Effect page →
View source code
HTML
<button class="pcr-card" type="button" aria-label="Hover or activate to curl the page and reveal the promo code">
              <div class="pcr-under"><div><strong>WELCOME20</strong><span>-20% on everything</span></div></div>
              <div class="pcr-page">Hover the corner ↗</div>
              <span class="pcr-curl" aria-hidden="true"></span>
            </button>
CSS
.pcr-card {
  position: relative;
  width: 250px;
  height: 160px;
  border-radius: 12px;
  overflow: hidden;
  background: #101018;
  border: 1px solid rgba(255,255,255,.08);
}

.pcr-under {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
  background: radial-gradient(circle at 70% 20%, rgba(34,255,170,.18), transparent 55%), #0d1512;
}

.pcr-under strong {
  font-size: 1.25rem; color: #22ffaa; letter-spacing: .06em
}

.pcr-under span {
  display: block; font-size: .68rem; color: #7fbfa8; margin-top: 4px; letter-spacing: .12em; text-transform: uppercase
}

.pcr-page {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, #262640, #16162a);
  color: #cfcfe8;
  font-size: .8rem;
  letter-spacing: .04em;
  clip-path: polygon(0 0, calc(100% - var(--pcr-c)) 0, 100% var(--pcr-c), 100% 100%, 0 100%);
  transition: clip-path .55s cubic-bezier(.25,.8,.3,1);
  --pcr-c: 34px;
}

.pcr-curl {
  position: absolute;
  top: 0; right: 0;
  width: var(--pcr-c);
  height: var(--pcr-c);
  --pcr-c: 34px;
  background: linear-gradient(225deg, transparent 48%, #3d3d66 50%, #52528a 70%, #2c2c4d 100%);
  border-bottom-left-radius: 55%;
  box-shadow: -5px 5px 12px rgba(0,0,0,.45);
  transition: width .55s cubic-bezier(.25,.8,.3,1), height .55s cubic-bezier(.25,.8,.3,1);
  pointer-events: none;
}

.pcr-card:hover .pcr-page, .pcr-card:focus-visible .pcr-page {
  --pcr-c: 150px
}

.pcr-card:hover .pcr-curl, .pcr-card:focus-visible .pcr-curl {
  width: 150px; height: 150px
}

.pcr-card:focus-visible {
  outline: 2px solid #a78bfa; outline-offset: 3px
}

.pcr-card[aria-pressed="true"] .pcr-page {
  --pcr-c: 380px
}

.pcr-card[aria-pressed="true"] .pcr-curl {
  width: 380px; height: 380px; opacity: 0; transition: width .6s cubic-bezier(.25,.8,.3,1), height .6s cubic-bezier(.25,.8,.3,1), opacity .35s ease .3s
}

.pcr-card[aria-pressed="true"]:hover .pcr-page {
  --pcr-c: 380px
}

@media (prefers-reduced-motion: reduce) {
  .pcr-page, .pcr-curl {
    transition: none
  }
}
JavaScript
(function() {
  /* fx-0775 — Page Curl Reveal : clic = révélation complète (toggle), survol = pli */
  document.querySelectorAll('.pcr-card').forEach(function(card) {
    card.setAttribute('aria-pressed', 'false');
    card.addEventListener('click', function() {
      card.setAttribute('aria-pressed', card.getAttribute('aria-pressed') !== 'true');
    });
  });
})();

Interactive Ghost Card

A true-3D neon collectible card: a ghost skull floats behind the glass and shifts perspective as the card turns. Drag it, hover it, or let it sway on its own.

💡 Perfect for: game cards, premium membership cards, drop launch pages.

WebGL Shader 3D Raymarching Drag Premium

Poster Pop-Out 3D

The poster tilts and its character steps out of the frame at the top, in relief, with a shadow and a colour glow. Hover, keyboard focus or tap; swap in your own posters.

💡 Perfect for: film or series posters, game covers, book covers.

CSS 3D Hover Poster Premium

Advent Calendar

Interactive advent calendar: 24 doors that open on a 3D hinge and reveal a bouncing surprise behind them, with the current day's door highlighted. Surprises and number of doors are customisable.

💡 Perfect for: December campaigns, gamification, loyalty programs, daily contests, progressive reveals, festive e-commerce.

Vanilla JS 3D Hinge Advent Premium

Ribbon Bow Wrap

Wraps a card in an animated golden ribbon with a knotting bow on hover. Click to lock the wrapping. Ribbon colour and card content are fully customisable — works on any card or offer.

💡 Perfect for: gift cards, Christmas offers, greeting messages, product highlights, digital packaging.

CSS Vanilla JS Festive Premium

Frequently Asked Questions

How to create a card with a tilt effect in CSS? +

The tilt effect requires JavaScript to track the mouse position. Calculate the X and Y rotation angles based on the cursor position relative to the card center. Apply transform: perspective(1000px) rotateX rotateY.

What is the best hover animation for a product card? +

The lift (translateY -8px + box-shadow) is the e-commerce standard. For more impact, add a border-color change and a slight scale increase (1.02). Keep the transition under 300ms.

How to create a card that flips on click? +

Use the flip technique: two faces (front/back) with backface-visibility:hidden. The back is pre-rotated 180deg. On click, add a class that rotates the container 180deg with a transition.

How to make a responsive card grid without media queries? +

Use CSS Grid with repeat(auto-fill, minmax(300px, 1fr)). Cards automatically reorganize based on available space. Add gap for spacing. No breakpoints needed.

How to animate cards appearing on scroll? +

Use IntersectionObserver to detect when cards enter the viewport. Add a class that triggers the animation (opacity:0 to 1, translateY:20px to 0). Add an incremental delay for a cascade effect.