Boutons✨ Premium

Gradient Border Animated

Un anneau de 2 px en dégradé conique rose → orange → turquoise dont l'angle de départ est animé de 0 à 360° en 3 s. Une condition souvent oubliée : la déclaration @property qui rend la variable --angle animable — sans elle, l'anneau est immobile.

CSSAnimationBorder

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

Générer une image — landing d'un outil d'IA créative — Gradient Border Animated exemple 1

① Générer une image — landing d'un outil d'IA créative

QuandHero sombre d'un générateur d'images : accroche, exemple de prompt, un bouton d'action.
PourquoiLe trio rose → orange → turquoise est une palette « créative » qui se distingue des indigos des SaaS ; l'anneau continu qui tourne évoque un traitement en cours, ce qui convient à un outil qui « fabrique ».
RéglagesTexte 16 px, padding: 18px 40px, tour en 4s, @property --angle déclaré une fois pour toute la page.
Suivre — carte de profil d'un créateur — Gradient Border Animated exemple 2

② Suivre — carte de profil d'un créateur

QuandCarte de profil : avatar, nom, statistiques, un bouton d'abonnement.
PourquoiSur une carte à fond sombre, l'anneau multicolore autour d'un bouton sombre reprend le code visuel des « stories » : coloré, animé, sans remplir le bouton. Un seul anneau par carte pour rester lisible.
RéglagesBouton compact (padding: 10px 22px, 13,5 px), border-radius: 999px sur les trois calques pour une pilule, tour en 3s.
Choisir un fichier — zone de dépôt d'un formulaire d'import — Gradient Border Animated exemple 3

③ Choisir un fichier — zone de dépôt d'un formulaire d'import

QuandZone de glisser-déposer : icône, consigne, formats acceptés et un bouton pour parcourir.
PourquoiL'anneau qui tourne signale la zone active de la carte sans texte clignotant ; à 2 px, il reste sobre dans une interface de travail. Le dégradé fait office d'indicateur « prêt à recevoir ».
RéglagesBouton padding: 11px 20px, 13,5 px, anneau 1.5px (::after { inset: 1.5px }), tour en 5s, face #12121a pour se détacher de la zone.

Comment ça marche

Trois calques, comme Rotating Border : le bouton .btn-gradient-border-anim (background: #0a0a0f, position: relative; z-index: 1, overflow: hidden; border-radius: 12px via .demo-btn), un ::before à z-index: -2 qui porte le dégradé (inset: -3px; border-radius: 15px) et un ::after à z-index: -1 qui redessine la face (inset: 2px; background: #0a0a0f; border-radius: 10px). L'écart de 2 px entre le bord du bouton et la face est l'anneau visible.

La différence avec Rotating Border est dans ce qui tourne. Ici la boîte ne bouge pas : le dégradé est conic-gradient(from var(--angle, 0deg), #ff0080, #ff8c00, #40e0d0, #ff0080) et l'animation rotateGradientAnim (3s linear infinite) fait varier --angle de 0deg à 360deg. Comme le ::before recouvre toujours tout le bouton, l'anneau devrait rester continu à tout instant — c'est le bon principe, celui qui évite les trous sur les flancs.

Mais une propriété personnalisée n'est interpolable que si elle est enregistrée avec @property. Sans cette déclaration, --angle est une chaîne pour le navigateur, qui l'anime de façon discrète — 0deg pendant la première moitié du cycle, 360deg pendant la seconde. Or 0° et 360° dessinent le même dégradé. Mesuré dans Chromium avec le CSS seul : --angle vaut 0deg à 0, 375, 750 et 1 125 ms, 360deg à 1 500 ms, et les pixels de l'anneau sont identiques à tous ces instants — le bouton est statique. C'est le symptôme d'un @property oublié.

La règle indispensable — @property --angle { syntax: '<angle>'; inherits: false; initial-value: 0deg }, une fois dans la feuille de style — fait tout basculer : l'angle passe par 45° à 375 ms et 90° à 750 ms, les couleurs défilent le long de l'anneau et le dégradé fait un tour complet toutes les 3 s, sans jamais rompre. Vérifiez qu'elle accompagne bien le CSS que vous collez. Aucune règle :hover ni :active : l'animation tourne en permanence.

Accessibilité

  • Contraste du texte : blanc sur #0a0a0f = 19,8:1, niveau AAA. La face est opaque : la couleur de page derrière ne change rien.
  • Contraste de l'anneau (WCAG 1.4.11, seuil 3:1 pour le contour d'un composant) : sur #0a0a0f, #ff0080 = 5,2:1, #ff8c00 = 8,5:1, #40e0d0 = 12:1 — le contour de 2 px est perceptible à tout instant du cycle, et il est continu, contrairement à Rotating Border.
  • prefers-reduced-motion absent du code : le dégradé tourne en permanence. Ajoutez @media (prefers-reduced-motion: reduce) { .btn-gradient-border-anim::before { animation: none } } — l'anneau reste, figé à 0°, complet et lisible.
  • Lecteurs d'écran : les deux pseudo-éléments ont content: "", rien n'est annoncé, le nom accessible est le libellé. Le bouton reste un <button> natif ; l'animation ne dépend pas du survol.
  • Focus : outline n'est pas touché, l'anneau de focus natif reste visible et n'est pas rogné par overflow: hidden. Cible ≈ 54 px de haut (padding 18 px + texte), au-dessus du minimum de 44 px.

Compatibilité navigateur

Requiert @property, conic-gradient() avec from var(), la propriété raccourcie inset et l'animation d'une propriété personnalisée. Aucun JavaScript, zéro dépendance.

Chrome 87+✓ Complet
Firefox 128+✓ Complet
Safari 16.4+✓ Complet
Edge 87+✓ Complet
Mobile iOS 16.4+✓ Complet
Android Chrome✓ Complet

Sans @property — Firefox avant 128, Safari avant 16.4, ou si la règle a été omise — l'anneau dégradé est présent mais immobile : un bouton à bordure conique fixe, lisible et complet. Sans inset (Safari avant 14.1, Firefox avant 66), les pseudo-éléments n'ont ni taille ni position et il ne reste que le texte blanc sur la face.

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
@property --angle (CSS — indispensable, une fois par feuille) type angle, valeur initiale 0deg @property --angle { syntax: '<angle>'; inherits: false; initial-value: 0deg } rend la variable interpolable. Sans elle, aucune rotation. Chrome 85+, Safari 16.4+, Firefox 128+.
animation-duration (CSS — ::before, rotateGradientAnim) 3s Durée d'un tour complet. 2s = vif ; 8s = lent, presque une respiration. La rotation est continue, contrairement à Rotating Border.
conic-gradient(from var(--angle), #ff0080, #ff8c00, #40e0d0, #ff0080) (CSS — ::before) rose → orange → turquoise → rose Couleurs de l'anneau. Répétez la première en dernier pour éviter un raccord net. Deux couleurs suffisent pour un anneau bicolore qui tourne.
inset (CSS — ::after) 2px Épaisseur de l'anneau : l'écart entre le bord du bouton et la face. 1px = filet ; 3px = cadre. Ajustez le border-radius de la face (12 − inset).
background (CSS — ::after) #0a0a0f Couleur de la face. Identique au fond du catalogue ; sur une autre page, alignez-la sur votre surface ou éclaircissez-la pour un bord propre.
border-radius (CSS — .demo-btn 12px / ::before 15px / ::after 10px) 12 / 15 / 10 px Arrondi des trois calques. Face = bouton − inset de la face. 999px partout = pilule ; l'anneau reste continu, puisque la boîte ne tourne pas.
animation-play-state (CSS — à ajouter) running paused au repos et running sous :hover::before pour un anneau immobile qui se met à tourner au survol, sans repartir de zéro.

FAQ

La déclaration @property, presque toujours. Le code anime --angle de 0 à 360°, mais une propriété personnalisée non enregistrée n'a pas de type : le navigateur ne peut pas calculer 45° entre les deux et bascule d'une valeur à l'autre à mi-parcours — or 0° et 360° donnent le même dégradé. Vérifiez qu'au début de votre CSS figure bien @property --angle { syntax: '<angle>'; inherits: false; initial-value: 0deg }. La rotation démarre immédiatement, sans autre changement. Si la règle est là et que rien ne bouge, votre navigateur ne connaît pas @property (question suivante).
Un anneau dégradé fixe : ils ne connaissent pas @property, donc --angle reste discret et 0° = 360°. Le bouton est complet et lisible, seule la rotation manque — un repli acceptable. Si la rotation est indispensable sur ces navigateurs, repliez-vous sur la technique de Rotating Border (tourner la boîte du ::before avec transform), en faisant du ::before un carré plus grand que la diagonale pour que l'anneau reste continu.
Parce qu'un rectangle qui tourne ne couvre plus les flancs d'un bouton large dès qu'il s'écarte de 0° ou 180° : l'anneau s'y interrompt. Animer l'angle du dégradé laisse la boîte en place et l'anneau intact à tout instant — c'est la bonne solution, au prix de @property. Le compromis universel est un ::before carré (width: 200%; aspect-ratio: 1, centré) tourné par transform : continu partout, mais plus lourd à composer que l'animation d'une variable.