Boutons✨ Premium

CTA Gradient Border

Un anneau de 2 px découpé au masque dans un dégradé indigo → rose → ambre qui glisse en boucle sur 4 s autour d'une face sombre ; au survol, il accélère à 1,5 s et un halo indigo apparaît — CSS seul.

CSSCTAGradient

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

Commencer gratuitement — landing d'un SaaS — CTA Gradient Border exemple 1

① Commencer gratuitement — landing d'un SaaS

QuandHero sombre : accroche, argument, un bouton principal et un lien secondaire.
PourquoiLe trio indigo → rose → ambre est la signature des CTA « premium » de 2024-2026 ; l'anneau qui glisse attire l'œil sur le seul bouton du hero sans remplir la face de couleur, ce qui garde le texte à 19,8:1.
RéglagesTexte 16 px, padding: 18px 40px, cycle 6s pour un hero calme, halo de survol porté à 0 0 40px rgba(99,102,241,.35).
Passer en Pro — carte de mise à niveau — CTA Gradient Border exemple 2

② Passer en Pro — carte de mise à niveau

QuandCarte d'offre dans une grille de prix ou un encart d'essai : avantages listés, un bouton de bascule.
PourquoiUn seul anneau animé dans la grille désigne le plan à pousser ; sur une face sombre identique aux autres boutons, c'est le contour qui hiérarchise, pas la couleur pleine.
RéglagesBouton pleine largeur de la carte, padding: 13px, dégradé réduit à deux couleurs (#6366f1, #ec4899) pour s'aligner sur l'accent du plan.
Découvrir la v2 — carte d'annonce de fonctionnalité — CTA Gradient Border exemple 3

③ Découvrir la v2 — carte d'annonce de fonctionnalité

QuandEncart de nouveauté dans un tableau de bord ou une fenêtre modale : étiquette « Nouveau », phrase, un bouton.
PourquoiL'anneau multicolore dit « nouveau » sans badge clignotant ; il tourne en continu mais ne fait que 2 px, ce qui le rend supportable dans une interface de travail. Le halo au survol confirme la cible.
RéglagesBouton compact (padding: 11px 20px, 13,5 px), border-radius: 10px (anneau à 12px), cycle 5s, padding: 1.5px sur le ::before pour un filet plus fin.

Comment ça marche

Le bouton .btn-cta-gradient est plein : background: #0a0a0f, color: #fff, padding: 18px 36px, position: relative; z-index: 1 et, via .demo-btn, overflow: hidden; border-radius: 12px. L'anneau est son ::before : inset: 0 (la taille exacte du bouton), padding: 2px, border-radius: 14px et un fond linear-gradient(135deg, #6366f1, #ec4899, #f59e0b) étiré à 300% 300%.

Le découpage vient de mask : deux calques, linear-gradient(#fff 0, #fff 0) content-box (un rectangle plein limité à la boîte de contenu, c'est-à-dire tout sauf les 2 px de padding) et linear-gradient(#fff 0, #fff 0) (la boîte entière), composés en exclude : là où les deux se recouvrent, le masque est vide. Il ne reste que la couronne de 2 px entre les deux boîtes. Mesuré dans Chromium : pixels colorés à 0 et 1 px du bord, face #0a0a0f à partir de 3 px.

Le mouvement est gradientMove : background-position va de 0 0 à 100% 100% et revient, en 4s ease infinite. Comme l'image fait trois fois la boîte, ce trajet fait défiler les trois couleurs le long de l'anneau — indigo à un coin, ambre à l'autre, rose entre les deux, puis inversion. Les keyframes déclarent deux positions (0 0, 100% 100%) pour un seul calque : la seconde est ignorée par le navigateur.

Au :hover, deux choses : box-shadow: 0 0 30px rgba(99,102,241,.3) sur le bouton (sans transition déclarée, donc instantané) et la même animation en 1.5s sur le ::before. Changer la durée ne redémarre pas l'animation : le navigateur conserve son currentTime. Mesuré : à 1,33 s dans le cycle de 4 s (33 %), le passage à 1,5 s place ce même instant à 89 % du nouveau cycle — le dégradé saute à une autre position à l'entrée du survol, puis à nouveau à la sortie. Voir la FAQ.

Accessibilité

  • Contraste du texte : blanc sur #0a0a0f = 19,8:1, niveau AAA — l'un des rares boutons du catalogue à passer sans retouche. La face est opaque : la couleur de page ne change rien.
  • Contraste de l'anneau (WCAG 1.4.11, seuil 3:1 pour le contour d'un composant) : sur la face sombre, #6366f1 = 4,4:1, #ec4899 = 5,6:1, #f59e0b = 9,2:1 — le contour de 2 px est perceptible à tout moment du cycle, sur un fond de page sombre comme clair.
  • prefers-reduced-motion absent du code : un dégradé qui glisse en permanence. Ajoutez @media (prefers-reduced-motion: reduce) { .btn-cta-gradient::before { animation: none } } — l'anneau reste, figé sur la position 0 0 (indigo → rose).
  • Repli dangereux sans mask : le code repose sur mask non préfixé. Sur Chrome avant 120 et Safari avant 15.4, le masque est ignoré, le ::before devient un rectangle dégradé plein qui se peint au-dessus du texte (il est positionné, donc peint après le contenu) : le bouton n'a plus de libellé visible. Doublez les déclarations en -webkit-mask / -webkit-mask-composite: xor, ou enveloppez le ::before dans @supports (mask-composite: exclude).
  • Clavier et tactile : rien ne dépend du survol pour l'essentiel — l'anneau tourne pour tout le monde. Le :hover n'ajoute qu'un halo et une accélération ; l'outline natif est conservé et n'est pas rogné par overflow: hidden. Cible ≈ 54 px de haut, au-dessus du minimum de 44 px.

Compatibilité navigateur

Requiert la propriété raccourcie mask sans préfixe avec mask-composite: exclude, inset et l'animation de background-position. Aucun JavaScript, zéro dépendance.

Chrome 120+✓ Complet
Firefox 53+✓ Complet
Safari 15.4+✓ Complet
Edge 120+✓ Complet
Mobile iOS 15.4+✓ Complet
Android Chrome 120+✓ Complet

Sans prise en charge de mask (Chrome avant 120, Safari avant 15.4), le pseudo-élément n'est plus découpé : un rectangle dégradé plein recouvre tout le bouton, libellé compris. Ajoutez les déclarations -webkit-mask et -webkit-mask-composite: xor, ou conditionnez le ::before à @supports (mask-composite: exclude) pour retomber sur un bouton sombre sans anneau.

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
animation-duration (CSS — ::before 4s / :hover::before 1.5s) 4s / 1.5s Vitesse du défilement au repos et au survol. Une valeur différente au survol provoque un saut de position (voir FAQ) ; gardez la même pour un mouvement continu.
linear-gradient(135deg, #6366f1, #ec4899, #f59e0b) (CSS — ::before) indigo → rose → ambre Couleurs de l'anneau. Deux couleurs suffisent ; plus il y a d'arrêts, plus le défilement paraît rapide à durée égale.
padding (CSS — ::before) 2px Épaisseur de l'anneau : c'est la zone entre la boîte de contenu (exclue par le masque) et le bord. 1px = filet ; 3px = cadre marqué.
background-size (CSS — ::before) 300% 300% Étirement du dégradé. Plus grand = transitions de couleur plus douces et défilement plus lent à durée égale ; 200% montre plus de couleurs à la fois.
background (CSS — .btn-cta-gradient) #0a0a0f Couleur de la face. Identique au fond du catalogue ; transparent laisse voir la page à travers, l'anneau seul dessine le bouton.
box-shadow (CSS — :hover) 0 0 30px rgba(99,102,241,.3) Halo au survol, instantané (aucune transition déclarée). Ajoutez transition: box-shadow .3s au bouton pour un fondu.
border-radius (CSS — .demo-btn 12px / ::before 14px) 12 / 14 px Arrondi du bouton et de l'anneau. Gardez-les égaux : à 14 px l'arc de l'anneau se creuse plus tôt que celui du bouton et laisse un fin croissant de face nue dans chaque coin.

FAQ

Parce que le survol change animation-duration (4 s → 1,5 s) sur une animation qui garde son currentTime : un instant situé à 33 % du cycle lent se retrouve à 89 % du cycle rapide, et la position du dégradé change d'un coup — puis à nouveau au retour. Pour accélérer sans saut, ne changez pas la durée : gardez 4s et ajoutez sur :hover::before une seconde animation superposée (animation: gradientMove 4s ease infinite, gradientMove 1.5s ease infinite ne fonctionne pas sur la même propriété), ou contentez-vous du halo comme retour de survol — c'est le choix le plus simple et le plus propre.
Le masque n'est pas pris en charge (Chrome avant 120, Safari avant 15.4). Le ::before n'est alors plus découpé : c'est un rectangle dégradé de la taille du bouton, positionné, donc peint au-dessus du texte qu'il recouvre entièrement. Deux protections : dupliquer les déclarations avec préfixe (-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask-composite: xor;), ce qui couvre Chrome 1–119 et Safari 4–15.3 ; et envelopper toute la règle ::before dans @supports (mask-composite: exclude) or (-webkit-mask-composite: xor) pour qu'un navigateur sans masque n'affiche qu'un bouton sombre, lisible, sans anneau.
Oui : .btn-cta-gradient { background: transparent }. Le masque ne concerne que le ::before, l'anneau reste identique et le texte se pose directement sur la page. Vérifiez alors le contraste du libellé blanc avec votre fond réel, et gardez z-index: 1 — il ne sert pas ici à empiler des calques négatifs, mais il isole le bouton et évite qu'un voisin positionné ne passe entre l'anneau et la face.