Cartes✨ Premium

Card Morph

La carte grossit au clic via une courbe back-ease-out, masque son aperçu et révèle son contenu par un fondu-scale — elle se referme d'un clic extérieur.

JSClickExpand

Vous aurez accès à la démo interactive avec un compte gratuit.

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Cartes comprend 41 effets, dont 6 gratuits. Découvrir la catégorie →

3 exemples d'usage

Dashboard SaaS — Carte de fonctionnalité interactive — Card Morph exemple 1

① Dashboard SaaS — Carte de fonctionnalité interactive

QuandDans un tableau de bord ou une page tarifaire, les fonctionnalités sont listées en grille de cartes compactes. L'utilisateur clique sur une carte pour lire sa description sans quitter la page.
PourquoiLa courbe élastique et la lueur violette rendent chaque carte distinctement cliquable — le détail surgit dans la carte elle-même, sans modal ni lien sortant.
Réglagestransform: scale(1.08) pour rester dans les limites de la grille parente, box-shadow en couleur brand (remplacer rgba(99,102,241,.3)), transition: .4s ease-out pour une ouverture plus directe.
Portfolio — Aperçu de projet qui s'ouvre sans changer de page — Card Morph exemple 2

② Portfolio — Aperçu de projet qui s'ouvre sans changer de page

QuandSur une galerie de projets, chaque carte affiche un aperçu miniature. L'utilisateur clique pour lire le résumé et la stack technique avant de décider de naviguer.
PourquoiLe fondu-scale de la couche .card-full-content simule l'ouverture d'un dossier — le projet « sort » visuellement du fond sans quitter la grille.
Réglages--radius-xl: 0.5rem pour des angles plus vifs, remplacer l'icône par une miniature image dans .card-preview, --text-muted: #a0aec0 pour un texte secondaire plus clair.
Catalogue musique — Carte album avec aperçu rapide — Card Morph exemple 3

③ Catalogue musique — Carte album avec aperçu rapide

QuandDans un lecteur ou une vitrine en grille serrée, un clic sur un album ouvre ses détails (titre, artiste, durée) sans interrompre la lecture en cours.
PourquoiLe scale(1.1) et le z-index: 10 de la carte expanded font « sortir » l'album de la grille — signal visuel fort de sélection, sans modal plein écran.
Réglagestransform: scale(1.15) pour une expansion plus affirmée, remplacer le dégradé de l'icône par la couleur dominante de la pochette, z-index: 20 sur .card-morph-expand.expanded pour passer au-dessus des cartes voisines.

Comment ça marche

Un gestionnaire de clic sur .card-morph-expand appelle classList.toggle('expanded'). Un second listener sur document détecte les clics extérieurs et retire la classe expanded automatiquement — pas de bouton de fermeture nécessaire.

L'animation est pilotée par une transition CSS : transition: .5s cubic-bezier(.175, .885, .32, 1.275). Cette courbe back ease-out produit un léger dépassement puis un retour élastique au scale(1.1) final, sans une ligne de JavaScript d'animation. Une ombre portée violette apparaît simultanément via box-shadow.

L'échange de contenu repose sur deux couches empilées en position: absolute; inset: 0. La couche aperçu (.card-preview) passe à opacity: 0 en 0,3 s. La couche contenu (.card-full-content) part de opacity: 0; transform: scale(.9) et rejoint opacity: 1; transform: scale(1) en 0,4 s, créant un surgissement centré.

Aucun requestAnimationFrame n'est utilisé : l'effet est 100 % CSS transitions sur bascule de classe. La .card-morph-expand porte overflow: hidden — le contenu ne déborde jamais hors des arrondis, même à scale(1.1).

Accessibilité

  • prefers-reduced-motion absent : le code ne contient pas de media query prefers-reduced-motion — les transitions scale et opacity s'exécutent toujours, même si l'OS demande à réduire le mouvement. À ajouter manuellement si nécessaire.
  • L'élément cliquable est une <div> sans role="button" ni gestionnaire keydown — inaccessible au clavier (Tab ne la sélectionne pas, Entrée/Espace n'ont pas d'effet).
  • Pas d'attribut aria-expanded : les lecteurs d'écran ne sont pas informés de l'état ouvert/fermé.
  • Le texte secondaire (--text-muted: #8b8b93) sur fond #12121a atteint un ratio de contraste d'environ 4,7:1 — conforme WCAG AA (≥ 4,5:1).
  • La cible de clic (280 × 180 px par défaut) dépasse largement les 44 × 44 px recommandés par WCAG 2.5.5.

Compatibilité navigateur

Nécessite CSS transitions et classList — supportés dans tous les navigateurs modernes depuis 2017. Zéro dépendance externe.

Chrome 60+✓ Complet
Firefox 55+✓ Complet
Safari 12+✓ Complet
Edge 79+✓ Complet
Mobile iOS✓ Touch OK
Android Chrome✓ Complet

Sans JS, la carte reste dans son état initial (aperçu visible). Les styles CSS sont autonomes — aucun flash ni mise en page brisée.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
<div class="demo-preview">
  <div class="card-demo card-morph-expand" id="morphExpandCard">
    <div class="card-preview">
      <div class="card-preview-icon">
        <!-- Icône SVG 24×24 -->
      </div>
      <span>Cliquez</span>
    </div>
    <div class="card-full-content">
      <h5>Titre du contenu révélé</h5>
      <p>Description détaillée affichée à l'expand.</p>
    </div>
  </div>
</div>
🔒 Débloquer le code complet — à partir de 2,99 € le 1er mois

HTML + CSS + JS complet, prêt à coller — avec des centaines d'effets premium.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
--bg-card #12121a Couleur de fond de la carte — remplacer par n'importe quelle couleur de votre design system.
--radius-xl 1rem Rayon d'arrondi des coins — 0.5rem pour un look card, 1.5rem pour un look pill.
--border rgba(255,255,255,0.08) Couleur du bord de la carte au repos — augmentez l'opacité pour un contour plus visible sur fonds clairs.
--text-primary #ffffff Couleur du titre dans le contenu révélé.
--text-muted #8b8b93 Couleur du texte secondaire dans le contenu révélé (ratio WCAG AA ≈ 4,7:1 sur --bg-card par défaut).
transition: .5s cubic-bezier(.175,.885,.32,1.275) .5s back-ease-out Durée et courbe de l'expansion — .3s ease-out pour un rendu plus direct, .7s pour un effet plus théâtral.
transform: scale(1.1) scale(1.1) Amplitude d'expansion dans .card-morph-expand.expandedscale(1.05) pour discret, scale(1.2) pour dramatique.
box-shadow rgba(99,102,241,.3) 0 25px 50px Couleur et portée de l'ombre au survol — changez la couleur RGBA pour correspondre à votre accent brand.
linear-gradient(135deg,#6366f1,#8b5cf6) indigo→violet Dégradé de l'icône ronde dans .card-preview-icon — remplacez par vos couleurs brand ou une image de fond.

FAQ

Le JS original cible l'id morphExpandCard — une seule instance. Pour plusieurs cartes, remplacez le getElementById par une boucle : document.querySelectorAll('.card-morph-expand').forEach(card => { card.addEventListener('click', () => card.classList.toggle('expanded')); }); et ajoutez document.addEventListener('click', e => document.querySelectorAll('.card-morph-expand').forEach(c => { if (!c.contains(e.target)) c.classList.remove('expanded'); })).
La <div> cliquable n'est pas focusable nativement. Deux correctifs : remplacez-la par un <button type="button" class="card-morph-expand"> (focusable, Entrée/Espace activent le clic), ou ajoutez tabindex="0" sur la div et un listener keydown qui appelle classList.toggle('expanded') sur Enter et Space. Mettez également aria-expanded à jour par JS.
Oui. Séparez les transitions : dans .card-morph-expand définissez transition: transform .35s ease-in, box-shadow .35s ease-in (fermeture rapide), puis dans .card-morph-expand.expanded surchargez avec transition: transform .5s cubic-bezier(.175,.885,.32,1.275), box-shadow .5s ease-out (ouverture élastique). CSS applique la règle active au moment de la transition.