Boutons✨ Premium

Morph

Au survol, le bouton violet grossit de 10 % et passe de coins à 12 px à une pilule (50 px) en 500 ms sur une courbe à rebond ; sa couleur unie bascule d'un coup vers un dégradé violet → fuchsia — CSS seul, sans état au clic.

CSSHoverTransform

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. Boutons comprend 27 effets, dont 2 gratuits. Découvrir la catégorie →

3 exemples d'usage

Écouter — carte d'album ou de playlist — Morph exemple 1

① Écouter — carte d'album ou de playlist

QuandCarte de lecteur musical : pochette, titre, artiste, un bouton de lecture.
PourquoiLe passage à la pilule évoque le bouton de lecture des applications de streaming, et le rebond de 500 ms donne un retour tactile à une carte par ailleurs immobile. Le violet → fuchsia s'accorde aux pochettes colorées.
RéglagesBouton compact (padding: 11px 22px, 14 px), scale(1.06) pour ne pas mordre sur la pochette, durée .4s.
Créer mon premier design — landing d'un outil créatif — Morph exemple 2

② Créer mon premier design — landing d'un outil créatif

QuandHero d'une application de création (design, vidéo, présentation) : titre, promesse, un seul bouton.
PourquoiLe morphing carré → pilule met en scène la transformation que promet l'outil. Sur un bouton isolé et généreux, le dépassement de 10 % a la place de s'exprimer sans recouvrir un voisin.
RéglagesTexte 17 px, padding: 18px 40px, courbe cubic-bezier(.68, -.6, .32, 1.6) pour un rebond plus marqué, dégradé #7c3aed → #c026d3 pour le contraste.
S'abonner — champ e-mail et bouton en ligne — Morph exemple 3

③ S'abonner — champ e-mail et bouton en ligne

QuandBloc newsletter : un champ de saisie et le bouton d'envoi côte à côte.
PourquoiLe bouton qui s'arrondit en pilule fait écho au champ arrondi à côté de lui ; c'est un retour visible sur la seule action du bloc. Le scale(1.1) le fait déborder de 5 px sur le champ : laissez un gap d'au moins 10 px.
Réglagesgap: 12px entre champ et bouton, scale(1.05), border-radius du champ = 50px pour une forme finale identique.

Comment ça marche

Deux états seulement : le repos (background: #8b5cf6, border-radius: 12px, scale(1)) et le :hover (border-radius: 50px, transform: scale(1.1), background: linear-gradient(135deg, #8b5cf6, #d946ef)). Aucun @keyframes, aucune règle :active : tout le mouvement est la transition entre ces deux états.

La transition : .5s cubic-bezier(.68, -.55, .265, 1.55) sur toutes les propriétés. Les points de contrôle hors de [0, 1] font sortir la courbe de l'intervalle départ → arrivée. Mesuré dans Chromium sur scale : recul à 0,9925 vers 60–100 ms (le bouton se contracte avant de grossir), dépassement à 1,107 vers 400 ms, puis pose à 1,1 à 500 ms. Le border-radius suit la même courbe : 12 → 50 px avec un pic à ≈ 52,7 px.

Sur un bouton de 50 px de haut, border-radius: 50px vaut une pilule complète (le rayon dépasse la demi-hauteur, le navigateur le plafonne). Le changement de forme et de taille est simultané : c'est cette combinaison, plus que le scale seul, qui donne l'impression que la matière se déforme. Le bouton passe de 113 × 50 px à 124 × 55 px à l'écran sans toucher à la mise en page (transform n'affecte pas les voisins) — il les recouvre de 5 px de chaque côté.

La couleur, elle, ne glisse pas : background-image n'est pas une propriété animable, et le raccourci background du survol remet background-color à transparent. Mesuré à +30 ms : le dégradé est déjà en place. La couleur bascule donc instantanément à l'entrée et à la sortie du survol, pendant que forme et taille rebondissent sur 500 ms — voir la FAQ pour un fondu.

Accessibilité

  • Contraste insuffisant dans la version fournie : texte blanc sur #8b5cf6 = 4,23:1, juste sous le seuil AA de 4,5:1 pour un texte de 16 px ; au survol, l'extrémité fuchsia du dégradé (#d946ef) tombe à 3,46:1. Passez à #7c3aed au repos (5,7:1) et à linear-gradient(135deg, #7c3aed, #c026d3) au survol (5,7:1 → 4,7:1), ou montez le libellé à 18 px gras (seuil 3:1, que l'original respecte).
  • prefers-reduced-motion absent du code : ajoutez @media (prefers-reduced-motion: reduce) { .btn-morph { transition: none } }. Forme, taille et couleur changent toujours au survol, mais sans rebond ni glissement.
  • Clavier : aucun :hover à la navigation Tab. Déclarez .btn-morph:focus-visible { border-radius: 50px; transform: scale(1.1); background: linear-gradient(135deg, #8b5cf6, #d946ef) } pour donner au focus le même relief, et gardez l'outline natif — le code ne le retire pas.
  • Lecteurs d'écran : l'effet est purement visuel, le bouton reste un <button> natif avec son libellé pour nom accessible. Rien à ajouter.
  • Tactile : sur iOS l'état :hover reste collé après un tap — le bouton demeure en pilule agrandie jusqu'au toucher suivant ; enveloppez la règle dans @media (hover: hover). Cible ≈ 50 px de haut (55 px au survol), au-dessus du minimum de 44 px.

Compatibilité navigateur

Requiert les transitions CSS de transform et border-radius avec cubic-bezier() — tous les navigateurs depuis 2012, valeurs de dépassement comprises. Aucun JavaScript, zéro dépendance.

Chrome 26+✓ Complet
Firefox 16+✓ Complet
Safari 9+✓ Complet
Edge 12+✓ Complet
Mobile iOS✓ Statique (pas de survol, état collant après un tap)
Android Chrome✓ Statique (pas de survol)

Sans transitions, les deux états s'appliquent instantanément : le bouton saute de sa forme carrée à la pilule agrandie, le dégradé apparaît de la même façon. Aucun navigateur n'anime le passage d'une couleur unie à un dégradé : ce saut de couleur est le comportement normal, pas un repli.

Le code

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

index.html — structure
🔒 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
cubic-bezier(.68, -.55, .265, 1.55) (CSS — transition) ≈ 0,75 % de recul puis 0,7 % de dépassement sur scale Ramenez le 2ᵉ et le 4ᵉ paramètre vers 0 et 1 pour calmer le rebond (.68, -.2, .265, 1.2) ; éloignez-les pour l'exagérer. Trop loin, border-radius passe sous 0 un instant : coins carrés.
transition-duration (CSS — .btn-morph) .5s Durée totale, rebond compris. .3s = réactif (la valeur de Gummy Elastic) ; .8s = gélatineux, à réserver à un gros bouton.
scale(1.1) (CSS — :hover) 1.1 Grossissement au survol. Sans effet sur la mise en page : le bouton recouvre ses voisins de 5 % de sa largeur de chaque côté. 1.04 dans une barre serrée.
border-radius (CSS — 12px repos / 50px survol) 12 / 50 px Forme de départ et d'arrivée. 50px = pilule pour tout bouton de moins de 100 px de haut ; 24px = simple arrondi accentué ; 0 au repos = carré qui devient galet.
background (CSS — :hover) linear-gradient(135deg, #8b5cf6, #d946ef) Couleur du bouton survolé. Bascule sans fondu (non animable). Une couleur unie à la place (#a855f7) redevient animable et glisse avec le reste.
background (CSS — .btn-morph) #8b5cf6 Couleur au repos. Pour un contraste AA avec le texte blanc : #7c3aed ou plus sombre.
transition-property (CSS — implicite) all Limitez à transform, border-radius pour que la courbe à rebond ne s'applique pas à une ombre ou une couleur ajoutées plus tard.

FAQ

Parce que le survol remplace une couleur unie par un linear-gradient, et que background-image n'est pas interpolable — aucun navigateur ne fond une couleur vers un dégradé. Pour un fondu, gardez background: #8b5cf6 sur le bouton, dessinez le dégradé dans un pseudo-élément (::before { inset: 0; background: linear-gradient(…); opacity: 0; transition: opacity .5s; border-radius: inherit }) et passez son opacity à 1 au survol — l'opacité s'anime, et border-radius: inherit lui fait suivre le morphing.
Le code n'a pas de règle :active. Ajoutez-en une après :hover : .btn-morph:active { transform: scale(.96); border-radius: 30px }. Déclarée après, elle l'emporte pendant l'appui, et le relâchement revient à la pilule par la même courbe de 500 ms — c'est exactement la construction de Gummy Elastic, en plus lent.
transform ne modifie pas la mise en page : le bouton survolé déborde de 5 % par côté sur ce qui l'entoure, et un voisin peint après lui le recouvre. Donnez au bouton position: relative; z-index: 1 (ou isolation: isolate sur son parent) pour qu'il passe au-dessus, et prévoyez un gap d'au moins 10 % de sa largeur si vous ne voulez aucun chevauchement.