Comment animer des cartes sans nuire à la lisibilité ?

Les effets de cartes rendent tangibles les contenus groupés : produits, articles, membres d'une équipe. Ils combinent les transformations CSS pour l'inclinaison et le soulèvement, backface-visibility pour les cartes qui se retournent, backdrop-filter pour les surfaces en verre, et CSS Grid avec les container queries pour des grilles Bento qui s'adaptent à leur propre largeur plutôt qu'à l'écran.

Comment choisir, performances et accessibilité
  • Utilisez un Hover Lift ou un 3D Tilt Effect discret sur les cartes produit cliquables, Flip Card quand le verso apporte une vraie information, et Stacked Cards ou Card Morph pour raconter une histoire.
  • Faites de toute la carte un seul lien ou bouton, gardez le texte lisible pendant le mouvement et réduisez l'inclinaison pour prefers-reduced-motion.
  • 3D Tilt Effect, Glassmorphism, Basic Bento, Holo Tilt & Glare, Foil Shimmer et Page Curl Reveal sont gratuits avec leur code ; les autres cartes sont incluses dans Premium.
3D Tilt

3D Tilt Effect

La carte s'incline selon la position de la souris.

JS 3D Interactive
Page de l’effet →
Voir le code source
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

Effet verre dépoli avec backdrop-filter blur.

CSS Glass Modern
Page de l’effet →
Voir le code source
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
/* CSS pur — aucun JavaScript requis */

Spotlight Effect

Lumière qui suit le curseur sur la carte.

JS Light Hover

Animated Border

Bordure gradient animée en continu.

CSS Gradient Loop

Flip Card

Retournement 3D au survol.

CSS 3D Flip

Hover Lift

Élévation et scale au survol avec ombre portée.

CSS Hover Shadow

Morphing Shape

Border-radius qui change continuellement.

CSS Animation Organic

Glow Pulse

Halo lumineux qui pulse en continu.

CSS Glow Loop

Stacked Cards

Les cartes s'écartent en éventail au survol.

CSS Stack Hover

Card Morph

La carte s'agrandit et révèle son contenu au clic.

JS Click Expand

Parallax Layers

Effet de profondeur avec plusieurs couches en 3D.

CSS 3D Parallax

Shine Effect

Reflet brillant qui traverse la carte au survol.

CSS Hover Light

Neumorphic

Style soft UI avec ombres douces et reliefs subtils.

CSS Soft UI Modern

Claymorphism

Style argile 3D avec effet de profondeur organique.

CSS 3D Organic

Content Reveal

Le contenu caché se révèle progressivement au survol.

CSS Hover Reveal

Image Zoom

L'image s'agrandit dans la carte au survol.

CSS Hover Image

Holographic

Effet holographique arc-en-ciel animé en continu.

CSS Rainbow Loop
Featured
A
B
Wide
C
D

Basic Bento

Grille bento simple avec animations au survol sur chaque cellule. Effet scale et glow.

CSS Grid Hover
Page de l’effet →
Voir le code source
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
/* CSS pur — aucun JavaScript requis */

Bento with Images

Cellules avec backgrounds gradient et overlay qui apparait au survol.

CSS Images Overlay

Animated Bento

Les cellules apparaissent en cascade avec un effet stagger au chargement.

CSS Animation Stagger

Interactive Bento

Cliquez sur une cellule pour l'agrandir. Cliquez à nouveau pour la réduire.

JS Click Expand

Bento with Stats

Affichage de statistiques avec animation des nombres au survol.

JS Stats Counter

Hover Reveal Bento

Le contenu se révèle au survol avec une transition fluide.

CSS Reveal Hover

Bento Card Stack

Cartes empilées qui se déploient en éventail au survol.

CSS Stack Cards

Responsive Bento

Grille qui se réorganise élégamment. Redimensionnez le conteneur pour voir l'effet.

CSS Responsive Auto-fit

Grid to List Toggle

Items morphing entre grid et list layout avec CSS grid transitions fluides.

CSS Grid FLIP

Card Expand to Full

Carte qui s'expanse de sa position vers le plein écran avec transition position/taille.

CSS JS FLIP

Tab Content Morph

Panneau d'onglets avec morphing crossfade et transition de position du contenu.

CSS JS Tabs

Masonry to Grid

Items qui animent d'un layout masonry organique vers une grille stricte et inversement.

CSS Layout Transition

Sidebar to Overlay

Sidebar qui se transforme en overlay plein écran avec reflow fluide du contenu.

CSS JS Layout

Split Screen Morph

Layout deux panneaux morphant entre 50/50, 70/30 et panneau unique avec transitions CSS flex.

CSS Flex Layout

Stacked to Spread

Cartes empilées en pile qui se repartissent en grille avec animation élastique cubic-bezier.

CSS Transform Elastic

Holographic Card 3D

Carte holographique iridescente au survol, style trading card premium. conic-gradient + blend modes + transform 3D. Zéro JavaScript.

CSS pur 3D Premium

Shape-Aware Shadows

Ombres, bordures et outline qui épousent des formes non rectangulaires grâce à border-shape : étiquette pointée, ticket à encoches, bulle de chat. Repli drop-shadow automatique sur tous les navigateurs.

💡 Idéal pour : badges promo, tickets d'événement, bulles de chat, tooltips pointés, cartes pricing.

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

Holo Tilt & Glare

Carte holographique pilotée au pointeur : tilt 3D (rAF + lerp), glare irisé qui suit le curseur et couche foil en parallaxe inverse — la profondeur d'une vraie carte holo. Retour élastique à la sortie, repli reduced-motion.

💡 Idéal pour : carte de fidélité premium, badge joueur, carte d'invitation, collectible.

JS Pointer 3D Holographic
Page de l’effet →
Voir le code source
HTML
<div class="htg-wrap" tabindex="0" aria-label="Carte holographique pilotée au pointeur">
  <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

Dorure holographique frappée en CSS pur : trois couches clippées au texte — gradient irisé animé, grain métallique, balayage specular. Variante pastille à bordure foil incluse. Survol = shimmer accéléré.

💡 Idéal pour : badge premium, titre de carte pricing, label d'édition limitée.

CSS Typography Hover Holographic
Page de l’effet →
Voir le code source
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
/* CSS pur — aucun JavaScript requis */

Holographic Sticker Peel

Sticker holographique die-cut qui se décolle : survol = le coin se soulève, clic = décollé aux trois quarts. Le verso expose colle grise et iridescence inversée — deux clip-path interpolés, ombre progressive, étirement « colle ».

💡 Idéal pour : sticker promo e-commerce, badge « nouveau », pastille événementielle.

CSS clip-path Click Premium

Prismatic Refraction Card

Verre à dispersion chromatique : les arêtes séparent la lumière en franges rouge/cyan pendant qu'une bande arc-en-ciel balaie la surface selon le curseur. Tilt 3D rAF + lerp, backdrop-filter saturé, lisibilité garantie par scrim.

💡 Idéal pour : carte pricing premium, hero de landing, widget de fonctionnalité phare.

CSS backdrop-filter Pointer Premium

Holo Pack Opening

Ouverture de booster façon TCG Pocket : une étincelle découpe le haut du sachet le long d'une ligne lumineuse, la languette s'arrache et virevolte, les cartes sortent par l'ouverture en cascade. Puis inspection — zoom auto, clic = retourner (flip 3D avec vrai dos), navigation ‹ › et clavier. 1 à N cartes, rejouable (nouveau pack), zéro dépendance.

💡 Idéal pour : reveal de récompense, carte cadeau, loot-box, onboarding gamifié.

JS clip-path Séquence Premium

Page Curl Reveal

Survolez : le coin se corne comme une vraie page. Cliquez : elle se corne entièrement et révèle le contenu caché, re-cliquez pour la reposer. Pli dégradé, ombre et clip-path animés, toggle accessible.

💡 Idéal pour : révéler un code promo, une surprise, un verso de carte, un teaser de contenu.

CSS clip-path Hover
Page de l’effet →
Voir le code source
HTML
<button class="pcr-card" type="button" aria-label="Survoler ou activer pour corner la page et révéler le code promo">
              <div class="pcr-under"><div><strong>WELCOME20</strong><span>-20 % sur tout</span></div></div>
              <div class="pcr-page">Survolez le coin ↗</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

Une carte à collectionner néon en vraie 3D : un crâne fantôme flotte derrière la vitre et change de perspective quand on la fait tourner. Glissez, survolez, ou laissez-la osciller.

💡 Idéal pour : carte de jeu, carte de membre premium, page de lancement d'un drop.

WebGL Shader 3D Raymarching Glisser Premium

Poster Pop-Out 3D

L'affiche s'incline et son personnage sort du cadre par le haut, en relief, avec ombre et halo de couleur. Survol, focus clavier ou tap ; remplacez les deux affiches par les vôtres.

💡 Idéal pour : affiche de film ou de série, jaquette de jeu, couverture de livre.

CSS 3D Hover Affiche Premium

Advent Calendar

Calendrier de l'avent interactif : 24 portes qui s'ouvrent sur charnière 3D et dévoilent une surprise en rebond, avec mise en avant de la case du jour. Surprises et nombre de cases personnalisables.

💡 Idéal pour : opération de décembre, gamification, fidélité, jeu-concours quotidien, dévoilement progressif, e-commerce festif.

Vanilla JS Charnière 3D Avent Premium

Ribbon Bow Wrap

Emballe une carte dans un ruban animé avec un nœud qui se noue, au survol. Clic pour verrouiller l'emballage. Couleur du ruban et contenu personnalisables — applicable à toute carte ou offre.

💡 Idéal pour : carte cadeau, offre de Noël, message de vœux, mise en avant d'un produit, packaging digital.

CSS Vanilla JS Festif Premium

Questions fréquentes

Comment créer une carte avec effet tilt en CSS ? +

L'effet tilt nécessite JavaScript pour tracker la position de la souris. Calculez l'angle de rotation X et Y base sur la position du curseur relative au centre de la carte. Appliquez transform: perspective(1000px) rotateX rotateY.

Quelle est la meilleure animation hover pour une carte produit ? +

Le lift (translateY -8px + box-shadow) est le standard e-commerce. Pour plus d'impact, ajoutez un changement de border-color et une légère augmentation de scale (1.02). Gardez la transition sous 300ms.

Comment créer une carte qui se retourne au clic ? +

Utilisez la technique flip : deux faces (avant/arrière) avec backface-visibility:hidden. L'arrière est pré-tourne de 180deg. Au clic, ajoutez une classe qui tourne le conteneur de 180deg avec transition.

Comment faire une grille de cartes responsive sans media query ? +

Utilisez CSS Grid avec repeat(auto-fill, minmax(300px, 1fr)). Les cartes se réorganisent automatiquement selon l'espace disponible. Ajoutez gap pour l'espacement. Pas besoin de breakpoints.

Comment animer l'apparition des cartes au scroll ? +

Utilisez IntersectionObserver pour détecter quand les cartes entrent dans le viewport. Ajoutez une classe qui déclenche l'animation (opacity:0 → 1, translateY:20px → 0). Ajoutez un delay incremental pour un effet de cascade.