Boutons✨ Premium

Bezier Elastic

Au survol, le bouton grossit à 1,08 et monte de 3 px avec une courbe qui dépasse sa cible de 9,8 % avant de s'y poser (pic à 1,088 vers 230 ms) ; au clic il se comprime à 0,95 en 100 ms. Trois états, une transition, aucun JavaScript.

CSSBezierElastic

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Boutons comprend 27 effets, dont 2 gratuits. Découvrir la catégorie →

3 exemples d'usage

Ajouter au panier — carte produit — Bezier Elastic exemple 1

① Ajouter au panier — carte produit

QuandCarte d'article : visuel, nom, prix, un bouton d'achat pleine largeur.
PourquoiLe rebond au relâchement du clic confirme physiquement l'ajout, sans attendre le panier ; au survol, le soulèvement isole la carte survolée dans une grille. Le cas d'usage était déjà noté sur l'ancienne fiche.
RéglagesDégradé #0e7490 → #155e75 (AA), scale(1.05), ombre rgba(14,116,144,.45).
Télécharger l'app — landing d'application mobile — Bezier Elastic exemple 2

② Télécharger l'app — landing d'application mobile

QuandLanding d'app : visuel du téléphone, promesse en une ligne, un bouton de téléchargement.
PourquoiUn bouton isolé, généreux, laisse la courbe s'exprimer : le dépassement de 10 % est visible à cette taille et donne au téléchargement un côté « prêt à bondir ». Le cas était sur l'ancienne fiche.
Réglagespadding: 18px 40px, .35s, courbe cubic-bezier(.34, 1.8, .64, 1) (dépassement 17,7 %).
Tourner la roue — carte de jeu à récompense — Bezier Elastic exemple 3

③ Tourner la roue — carte de jeu à récompense

QuandCarte de mini-jeu : une roue, un solde de tickets, le bouton qui lance la partie.
PourquoiL'univers ludique supporte l'exagération : grossissement plus fort, compression plus marquée, ombre colorée — le bouton devient un objet qu'on presse.
Réglagesscale(1.12) translateY(-4px), :active à scale(.9), courbe cubic-bezier(.34, 2, .64, 1) (dépassement 25 %).

Comment ça marche

Trois états et pas de @keyframes : le repos (dégradé cyan #06b6d4 → #0891b2, texte blanc), le :hover (transform: scale(1.08) translateY(-3px) et box-shadow: 0 15px 35px rgba(6,182,212,.4)) et le :active (transform: scale(.95)). Le mouvement n'est que la transition entre eux : transition: .4s cubic-bezier(.34, 1.56, .64, 1) — toutes propriétés, 400 ms.

La courbe est un « back-out » : son deuxième point de contrôle a une ordonnée de 1,56, au-dessus de 1. La valeur atteint la cible à 37 % du temps (≈ 150 ms), la dépasse de 9,8 % de la distance à 57 % (≈ 230 ms), puis revient s'y poser. Mesuré dans Chromium : l'échelle passe de 1 à un pic de 1,088 à 226 ms, puis 1,08 à 400 ms ; la translation culmine à −3,58 px avant −3,24 px. Deux détails : translateY est écrit après scale, il est donc multiplié par 1,08 — le bouton monte de 3,24 px, pas de 3 ; et l'ombre suit la même courbe, son décalage et son flou dépassent aussi.

Au clic, :active impose transition: .1s : le raccourci remplace toute la transition — 100 ms, courbe ease par défaut, sans dépassement. La pression est un claquement, pas un rebond. La règle omet translateY : le bouton redescend aussi de 3 px. Elle ne touche pas à box-shadow : l'ombre du survol reste sous un bouton pourtant comprimé. Déclaré après :hover, :active l'emporte tant que le bouton de la souris est enfoncé.

Au relâchement, la règle :active disparaît et c'est la transition de l'état survolé qui joue le retour : 400 ms élastiques de 0,95 vers 1,08. Le dépassement étant proportionnel à la distance (0,13 au lieu de 0,08), il est plus visible : pic mesuré à 1,0927 vers 245 ms. C'est le rebond de relâchement, plus que le survol, qui fait l'effet. Quand le curseur quitte le bouton, retour à 1 par la même courbe, avec un creux fugace vers 0,992.

Accessibilité

  • Contraste insuffisant : texte blanc sur #06b6d4 = 2,43:1 et sur #0891b2 = 3,68:1 — sous le seuil AA de 4,5:1 sur tout le dégradé, et sous 3:1 sur sa moitié claire. Gardez la teinte et assombrissez : #0e7490 → #155e75 donne 5,4:1 et 7,3:1. Un texte sombre (#083344) ne suffirait pas : 5,5:1 sur le clair, 3,6:1 sur le foncé. Le grossissement ne change rien au contraste.
  • prefers-reduced-motion absent du code : @media (prefers-reduced-motion: reduce) { .btn-bezier-elastic { transition: none } } — les états s'appliquent instantanément. Pour supprimer aussi le mouvement lui-même, ajoutez .btn-bezier-elastic:hover { transform: none } dans la même règle : l'ombre seule signale le survol.
  • Clavier : :active s'applique pendant l'appui sur Espace dans la plupart des navigateurs — la compression existe au clavier —, mais aucun :hover au focus. Ajoutez .btn-bezier-elastic:focus-visible { transform: scale(1.08) translateY(-3px); box-shadow: 0 15px 35px rgba(6,182,212,.4) }. L'outline natif est conservé et suit la transformation.
  • Encombrement : au pic, un bouton de 160 px fait 174 px de large et 55 px de haut, et son ombre s'étend 35 px de flou plus bas. Laissez au moins 8 px de marge entre deux boutons, et un z-index au survol si le bouton chevauche un voisin. Cible ≈ 51 px de haut au repos, au-dessus du minimum de 44 px.
  • Tactile : :active se déclenche au toucher — la compression est un bon retour mobile ; sur iOS, l'état survolé reste collé après le tap (@media (hover: hover)). Lecteurs d'écran : rien de généré, nom accessible = libellé du <button> natif.

Compatibilité navigateur

Requiert les transitions CSS de transform et box-shadow avec une cubic-bezier() dont les ordonnées sortent de [0, 1] — autorisé par la spécification et pris en charge partout depuis 2012. Aucun JavaScript, zéro dépendance.

Chrome 26+✓ Complet
Firefox 16+✓ Complet
Safari 9+✓ Complet
Edge 12+✓ Complet
Mobile iOS✓ Complet (:hover collant après un tap)
Android Chrome✓ Complet

Sans transitions, les trois états s'appliquent instantanément : le bouton grossit, se comprime et revient d'un coup — utilisable, sans rebond.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :

index.html — structure
<button class="demo-btn btn-bezier-elastic">Elastic</button>
Débloquer le code complet — 9,90 € TTC/mois

Le code complet HTML + CSS + JS de Bezier Elastic, prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.

Personnaliser

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

Option / propriétéDéfautEffet
cubic-bezier(.34, 1.56, .64, 1) (CSS — transition) dépassement 9,8 % Le 2ᵉ paramètre règle le rebond : 1.2 ≈ 1 %, 1.4 ≈ 5 %, 1.56 ≈ 10 %, 1.8 ≈ 18 %, 2 = 25 %. Au-delà, le dépassement devient caricatural et l'ombre « saute ».
.4s (CSS — transition-duration) .4s Durée totale, rebond compris. .25s : vif, le dépassement se sent à peine ; .6s : le bouton flotte.
scale(1.08) translateY(-3px) (CSS — :hover) 1.08 / −3 px Grossissement et soulèvement. L'ordre compte : translateY après scale est multiplié par l'échelle (3 × 1,08 = 3,24 px). Écrivez translateY(-3px) scale(1.08) pour 3 px exactement.
scale(.95) + transition: .1s (CSS — :active) .95 en 100 ms Profondeur et vitesse de la pression. scale(.92) : plus marqué ; .15s : plus mou. Ajoutez box-shadow: 0 4px 12px rgba(6,182,212,.3) pour que l'ombre se rapproche avec le bouton au lieu de rester à 15 px.
box-shadow: 0 15px 35px rgba(6,182,212,.4) (CSS — :hover) ombre cyan, 15 px sous le bouton Ombre colorée de la teinte du dégradé — un halo plus qu'une ombre. rgba(0,0,0,.3) : ombre portée neutre ; 0 8px 20px : plus proche, plus discrète.
linear-gradient(135deg, #06b6d4, #0891b2) (CSS — background) cyan clair → cyan Pour le contraste AA avec du texte blanc : #0e7490 → #155e75. Changez la couleur de l'ombre en même temps.
transition-property (CSS — implicite) all Restreignez à transform, box-shadow : un changement de couleur ou de fond (thème, état désactivé) ne rebondira pas avec la même courbe.

FAQ

Parce que le dépassement de la courbe est proportionnel à la distance parcourue — 9,8 % dans les deux cas. Au survol, l'échelle va de 1 à 1,08 (distance 0,08) : pic à 1,088. Au relâchement, de 0,95 à 1,08 (distance 0,13) : pic à 1,093. Le même mécanisme rend le retour au repos presque invisible (creux à 0,992).
Parce que transition: .1s est un raccourci : le réécrire remet toutes ses composantes à leur valeur par défaut, donc transition-timing-function: ease. La pression se fait en 100 ms sans dépassement — c'est voulu, un clic doit être sec. Pour une pression élastique, écrivez transition-duration: .1s seul : la courbe du survol est conservée.
Au pic il déborde de 7 px de chaque côté et son ombre porte 35 px de flou vers le bas. Trois précautions : au moins 8 px de marge autour, z-index: 1 sur :hover (le bouton est déjà position: relative) pour qu'il passe au-dessus des éléments suivants, et un conteneur sans overflow: hidden, qui rognerait le dépassement et l'ombre.