Comment animer un bouton pour qu'il donne envie de cliquer ?

Un bouton animé utilise le mouvement pour montrer qu'il est cliquable et pour confirmer le clic. Les techniques fiables sont les transitions CSS sur transform, box-shadow et background-position, les pseudo-éléments pour les reflets et les bordures, et quelques lignes de JavaScript pour l'onde au clic ou l'attraction magnétique vers le pointeur.

Comment choisir, performances et accessibilité
  • Pour l'appel à l'action principal, préférez un seul signal clair, comme Glow Pulse, Shine Sweep ou Gradient Shift, plutôt que plusieurs à la fois ; gardez Magnetic Button ou Liquid Fill pour les sites créatifs.
  • Faites court (environ 150 à 300 ms), donnez le même retour aux utilisateurs du clavier avec :focus-visible et n'exprimez jamais un état par le seul mouvement.
  • Gradient Shift et Ripple Effect sont gratuits avec leur code complet ; les autres boutons de la page sont inclus dans Premium.

Gradient Shift

Le gradient se déplace au survol créant un effet de mouvement fluide.

CSS Hover Gradient
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <button class="demo-btn btn-gradient-shift">Gradient Shift</button>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.demo-btn {
  padding: 16px 32px;
  font-size: 1rem;
  font-weight: 600;
  border: none;
  border-radius: 12px;
  cursor: pointer;
  font-family: inherit;
  position: relative;
  overflow: hidden;
}

.btn-gradient-shift {
  background: linear-gradient(135deg, #6366f1, #8b5cf6, #d946ef);
  background-size: 200% 200%;
  color: white;
  transition: all 0.5s ease;
}

.btn-gradient-shift:hover {
  background-position: 100% 100%;
  transform: translateY(-3px);
  box-shadow: 0 15px 35px rgba(99, 102, 241, 0.4);
}
JavaScript
/* CSS pur — aucun JavaScript requis */

Ripple Effect

Effet d'ondulation au clic inspiré de Material Design.

JS Click Animation
Page de l’effet →
Voir le code source
HTML
<div class="demo-preview">
  <button class="demo-btn btn-ripple" onclick="createRipple(event)">Ripple Effect</button>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 250px;
  overflow: hidden;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.demo-btn {
  padding: 16px 32px;
  font-size: 1rem;
  font-weight: 600;
  border: none;
  border-radius: 12px;
  cursor: pointer;
  font-family: inherit;
  position: relative;
  overflow: hidden;
}

.btn-ripple {
  background: #6366f1;
  color: white;
  transition: all 0.3s ease;
}

.btn-ripple .ripple-circle {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
  transform: scale(0);
  animation: ripple 0.6s linear;
  pointer-events: none;
}

@keyframes ripple {
  to {
    transform: scale(4);
    opacity: 0;
  }
}
JavaScript
(function() {
  // Ripple Effect
  function createRipple(e) {
    const btn = e.currentTarget;
    const rect = btn.getBoundingClientRect();
    const circle = document.createElement('span');
    const diameter = Math.max(btn.clientWidth, btn.clientHeight);
    const radius = diameter / 2;

    circle.style.width = circle.style.height = `${diameter}px`;
    circle.style.left = `${e.clientX - rect.left - radius}px`;
    circle.style.top = `${e.clientY - rect.top - radius}px`;
    circle.classList.add('ripple-circle');

    const ripple = btn.querySelector('.ripple-circle');
    if (ripple) ripple.remove();

    circle.addEventListener('animationend', () => circle.remove());
    btn.appendChild(circle);
  }
  window.createRipple = createRipple;
})();

Magnetic Button

Le bouton suit le curseur avec un effet d'attraction magnétique.

JS Mouse Interactive

Border Draw

Les bordures se dessinent progressivement au survol.

CSS Hover Border

Shine Sweep

Un reflet lumineux traverse le bouton au survol.

CSS Hover Shine

Glow Pulse

Halo lumineux qui pulse continuellement pour attirer l'attention.

CSS Animation Glow

3D Press

Effet de bouton physique avec profondeur et feedback au clic.

CSS 3D Active

Liquid Fill

Remplissage progressif comme un liquide qui monte.

CSS Hover Fill

Icon Slide

Icône qui apparaît en glissant au survol.

CSS Hover Icon

Neon Glow

Effet néon cyberpunk avec lueur intense au survol.

CSS Hover Neon

Rotating Border

Bordure en gradient qui tourne continuellement.

CSS Animation Border

Morph

Transformation de forme avec effet élastique.

CSS Hover Transform

Particle Trail

Traînée de particules colorées qui suivent le curseur au survol.

JS Mouse Particles

Split Text

Le texte se sépare lettre par lettre au survol puis se reforme.

JS Hover Text

Fill Slide Up

Remplissage de bas en haut avec courbe ease-quart. Inspiré de Daily Delights.

CSS Hover Fill

Press Feedback

Micro-interaction tactile avec compression au clic pour un feedback utilisateur optimal.

CSS Active Micro

Bezier Elastic

Animation avec courbe cubic-bezier élastique pour un effet rebond naturel.

CSS Bezier Elastic

Slide Reveal

Le texte glisse vers le haut pour révéler un nouveau texte coloré.

CSS Text Reveal

CTA Gradient Border

Bordure gradient animée parfaite pour les call-to-action premium. Inspiré de CTA Gallery.

CSS CTA Gradient

Neon Pulse

Box-shadow neon pulsant avec animation continue pour un effet cyberpunk intense.

CSS Animation Neon

Gummy Elastic

Effet élastique au clic avec courbe cubic-bezier pour un rebond naturel et fun.

CSS Hover Elastic

Glitch Effect

Effet glitch avec pseudo-éléments et décalage chromatique style rétro gaming.

CSS Animation Glitch

RGB Split

Séparation des canaux RGB au hover pour un effet aberration chromatique.

CSS Hover RGB

3D Depth Press

Effet profondeur avec ombre portée et feedback physique au clic.

CSS 3D Active

Neumorphic

Effet soft UI/neumorphism avec ombres douces et inversion au clic.

CSS Soft UI Active

Gradient Border Animated

Bordure dégradée tournante avec animation continue utilisant @property CSS.

CSS Animation Border

Slide Reveal Icon

Icône qui apparaît progressivement au hover avec expansion fluide.

CSS Hover Icon
0

Casque Studio Pro

149 €

Magnetic Add to Cart

Micro-interaction d'ajout au panier : bouton magnétique, burst de particules, vol de l'article jusqu'au panier et compteur animé. La satisfaction qui pousse à l'achat.

💡 Idéal pour : e-commerce, page produit, Black Friday, panier, tout CTA « ajouter / sauvegarder / aimer ».

Vanilla JS Micro-interaction E-commerce Gratuit
Voir le code source
HTML
<div class="demo-preview">
  <div class="atc-scene" data-atc data-icon="🎧">
    <div class="atc-cart-wrap">
      <span class="atc-cart" aria-hidden="true">🛒</span>
      <span class="atc-count" data-atc-count aria-label="Articles dans le panier">0</span>
    </div>
    <div class="atc-product">
      <div class="atc-thumb" aria-hidden="true">🎧</div>
      <div class="atc-info">
        <h3>Casque Studio Pro</h3>
        <span class="atc-price">149 €</span>
        <div><button type="button" class="atc-btn" data-atc-btn>Ajouter au panier</button></div>
      </div>
    </div>
  </div>
</div>
CSS
.demo-preview,
.demo-preview *,
.demo-preview *::before,
.demo-preview *::after {
  box-sizing: border-box
}

.demo-preview {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  min-height: 200px;
  position: relative;
  background: rgb(26, 26, 36);
  color: rgb(255, 255, 255);
  font-family: sans-serif;
}

.atc-scene {
  position: relative;
  width: 100%;
  min-height: 240px;
  border-radius: 14px;
  overflow: hidden;
  isolation: isolate;
  background: radial-gradient(circle at 70% 20%, #1c1330, #0b0a14 75%);
  padding: 22px;
  box-sizing: border-box;
}

.atc-cart {
  position: absolute;
  top: 16px;
  right: 18px;
  font-size: 26px;
  line-height: 1;
}

.atc-count {
  position: absolute;
  top: -8px;
  right: -10px;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  box-sizing: border-box;
  background: #ef4444;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border-radius: 999px;
  display: grid;
  place-items: center;
}

.atc-cart-wrap {
  position: absolute;
  top: 16px;
  right: 18px;
}

.atc-product {
  display: flex;
  align-items: center;
  gap: 16px;
  max-width: 360px;
  margin-top: 34px;
}

.atc-thumb {
  width: 78px;
  height: 78px;
  border-radius: 14px;
  background: linear-gradient(135deg, #6366f1, #d946ef);
  display: grid;
  place-items: center;
  font-size: 38px;
  flex: none;
}

.atc-info h3 {
  margin: 0 0 2px;
  font-size: 16px;
  color: #fff;
}

.atc-info .atc-price {
  color: #a78bfa;
  font-weight: 700;
}

.atc-btn {
  margin-top: 14px;
  border: 0;
  cursor: pointer;
  background: linear-gradient(135deg, #f59e0b, #ef4444);
  color: #fff;
  font-weight: 700;
  font-size: 14px;
  padding: 11px 20px;
  border-radius: 10px;
  transition: transform .12s, box-shadow .2s;
  will-change: transform;
}

.atc-btn:hover {
  box-shadow: 0 8px 24px rgba(245, 158, 11, .35);
}

.atc-btn:active {
  transform: scale(.96);
}

.atc-particle {
  position: absolute;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #fbbf24;
  pointer-events: none;
  transform: translate(-50%, -50%);
  animation: atc-burst .6s ease-out forwards;
  z-index: 4;
}

.atc-fly {
  position: absolute;
  font-size: 30px;
  pointer-events: none;
  z-index: 5;
  transform: translate(-50%, -50%);
}

.atc-pop {
  animation: atc-pop .32s ease;
}

.atc-bump {
  animation: atc-bump .4s ease;
}

@media (prefers-reduced-motion: reduce) {
  .atc-btn {
    transition: none;
  }
}

@keyframes atc-burst {
  to {
    transform: translate(-50%, -50%) translate(var(--dx), var(--dy)) scale(.2);
    opacity: 0;
  }
}

@keyframes atc-pop {
  0% {
    transform: scale(1);
  }

  40% {
    transform: scale(1.6);
  }

  100% {
    transform: scale(1);
  }
}

@keyframes atc-bump {

  0%,
  100% {
    transform: translateY(0);
  }

  30% {
    transform: translateY(-7px) rotate(-8deg);
  }
}
JavaScript
(function() {
  (function() {
    var reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

    document.querySelectorAll('[data-atc]').forEach(function(scene) {
      var btn = scene.querySelector('[data-atc-btn]');
      var cart = scene.querySelector('.atc-cart');
      var countEl = scene.querySelector('[data-atc-count]');
      var icon = scene.dataset.icon || '🛍️';
      var n = 0;

      if (!reduceMotion) {
        btn.addEventListener('pointermove', function(e) {
          var r = btn.getBoundingClientRect();
          var mx = e.clientX - (r.left + r.width / 2),
            my = e.clientY - (r.top + r.height / 2);
          btn.style.transform = 'translate(' + (mx * 0.22) + 'px,' + (my * 0.35) + 'px)';
        });
        btn.addEventListener('pointerleave', function() {
          btn.style.transform = '';
        });
      }

      function bump() {
        n++;
        countEl.textContent = n;
        countEl.classList.remove('atc-pop');
        void countEl.offsetWidth;
        countEl.classList.add('atc-pop');
        cart.classList.remove('atc-bump');
        void cart.offsetWidth;
        cart.classList.add('atc-bump');
      }

      btn.addEventListener('click', function() {
        if (reduceMotion) {
          bump();
          return;
        }
        var br = btn.getBoundingClientRect(),
          cr = cart.getBoundingClientRect(),
          sr = scene.getBoundingClientRect();
        var x0 = br.left + br.width / 2 - sr.left,
          y0 = br.top + br.height / 2 - sr.top;
        var x1 = cr.left + cr.width / 2 - sr.left,
          y1 = cr.top + cr.height / 2 - sr.top;

        for (var i = 0; i < 14; i++) {
          var p = document.createElement('span');
          p.className = 'atc-particle';
          p.style.left = x0 + 'px';
          p.style.top = y0 + 'px';
          var a = Math.random() * 6.2832,
            d = 24 + Math.random() * 46;
          p.style.setProperty('--dx', Math.cos(a) * d + 'px');
          p.style.setProperty('--dy', Math.sin(a) * d + 'px');
          scene.appendChild(p);
          (function(el) {
            setTimeout(function() {
              el.remove();
            }, 650);
          })(p);
        }

        var chip = document.createElement('span');
        chip.className = 'atc-fly';
        chip.textContent = icon;
        chip.style.left = x0 + 'px';
        chip.style.top = y0 + 'px';
        scene.appendChild(chip);
        var t0 = performance.now(),
          dur = 620,
          cx = (x0 + x1) / 2,
          cy = Math.min(y0, y1) - 70;
        (function anim(t) {
          var k = Math.min((t - t0) / dur, 1);
          var e = k < .5 ? 2 * k * k : 1 - Math.pow(-2 * k + 2, 2) / 2,
            m = 1 - e;
          var x = m * m * x0 + 2 * m * e * cx + e * e * x1;
          var y = m * m * y0 + 2 * m * e * cy + e * e * y1;
          chip.style.transform = 'translate(-50%,-50%) translate(' + (x - x0) + 'px,' + (y - y0) + 'px) scale(' + (1 - 0.55 * e) + ')';
          chip.style.opacity = String(1 - 0.25 * e);
          if (k < 1) requestAnimationFrame(anim);
          else {
            chip.remove();
            bump();
          }
        })(t0);
      });
    });
  })();
})();

Questions fréquentes

Comment animer un bouton au survol en CSS ? +

Utilisez la propriété CSS transition sur les propriétés que vous souhaitez animer (background, transform, box-shadow), puis définissez l'état final dans le sélecteur :hover. Par exemple : transition: all 0.3s ease; sur le bouton, puis transform: translateY(-2px) sur :hover.

Quel est le meilleur effet hover pour un bouton CTA ? +

Les effets les plus efficaces pour un CTA sont le gradient shift (mouvement de couleur), le glow (lueur autour du bouton) et le scale-up (léger agrandissement). Ils attirent l'oeil sans distraire. Évitez les animations trop longues (plus de 0.4s) qui ralentissent l'utilisateur.

Comment créer un bouton neon en CSS ? +

L'effet neon utilise box-shadow avec plusieurs couches de couleur. Appliquez 2-3 box-shadow avec des tailles croissantes et une couleur vive (ex: #6366f1). Ajoutez text-shadow pour faire briller le texte. Animez l'intensité au hover pour un effet pulse.

Les animations de boutons impactent-elles les performances ? +

Les animations CSS utilisant transform et opacity sont optimisées par le GPU et n'impactent pas les performances. Évitez d'animer width, height ou margin qui déclenchent un recalcul de layout. Utilisez will-change: transform sur les boutons animés pour préparer le navigateur.

Comment rendre un bouton animé accessible ? +

Ajoutez toujours un aria-label si le texte n'est pas descriptif. Respectez un contraste minimum de 4.5:1. Supportez prefers-reduced-motion avec une media query qui désactive les animations. Assurez-vous que le bouton est navigable au clavier avec un focus visible.