Écrivez moins. Livrez plus.
Rédaction, résumés et traduction dans les outils que vous utilisez déjà. Sans carte bancaire · 14 jours d'essaiSurvolez le bouton
Un dégradé indigo → violet → fuchsia peint deux fois plus grand que le bouton : au survol, la fenêtre visible glisse de la moitié indigo à la moitié fuchsia en 500 ms, avec un soulèvement de 3 px et un halo indigo — CSS seul, aucune @keyframes.
Cet effet est gratuit — la catégorie Boutons en contient 27 au total, dont 2 gratuits. Effect.Labs regroupe 811 effets vanilla. Découvrir la catégorie →
Écrivez moins. Livrez plus.
Rédaction, résumés et traduction dans les outils que vous utilisez déjà. Sans carte bancaire · 14 jours d'essaiSurvolez le bouton
Survolez le bouton Pro
Survolez le bouton
La base est la règle partagée .demo-btn : padding: 16px 32px, texte 1 rem semi-gras, border: none (livré sous ses quatre formes longues border-width/style/color/image), border-radius: 12px — 170 × 50 px mesurés dans Chromium pour le libellé de la démo. Le dégradé est dans le raccourci background de .btn-gradient-shift : linear-gradient(135deg, #6366f1, #8b5cf6, #d946ef) 0% 0% / 200% 200%, soit l'image de dégradé (position 0% 0%, taille 200% 200%) peinte sur deux fois la largeur et deux fois la hauteur du bouton — 340 × 100 px pour la démo. Seul le quart haut-gauche est visible au repos : la première moitié de la rampe, indigo → violet (mesuré #6865f2 dans le coin haut-gauche, #865df6 dans le coin bas-droit).
Au :hover, background-position: 100% 100% déplace la fenêtre visible sur le quart bas-droit de l'image : la seconde moitié de la rampe, violet → fuchsia (mesuré #9459f5 → #cf48ef). Le dégradé lui-même ne change pas, c'est la fenêtre qui glisse le long de la diagonale à 135°. transition: 0.5s — forme courte de all .5s ease — anime ce glissement : à 250 ms, la position est déjà à 80 % et le soulèvement à −2,4 px ; la courbe ease fait l'essentiel du trajet dans la première moitié et se pose doucement.
Deux autres déclarations partagent la même transition : transform: translateY(-3px), qui soulève le bouton sans toucher à la mise en page, et box-shadow: 0 15px 35px rgba(99, 102, 241, .4), un halo de la couleur du premier arrêt, décalé de 15 px vers le bas et flouté sur 35 px — il porte jusqu'à 50 px sous le bouton (mesuré : #202148 à 6 px sous le bord sur le fond #0a0a0f, revenu au fond vers 45 px). Au départ du curseur, les trois propriétés reviennent par la même courbe de 500 ms.
Pourquoi ce détour : un linear-gradient() est une image, et une transition ne sait pas interpoler entre deux images — changer les arrêts de couleur au survol ferait sauter le dégradé d'un coup. Peindre le dégradé plus grand et animer background-position, une simple longueur, est la technique standard pour le faire glisser. Aucun JavaScript, aucune @keyframes, aucun pseudo-élément. position: relative et overflow: hidden, hérités de .demo-btn, ne servent pas ici (pas d'enfant à découper) et ne gênent pas.
#6366f1 = 4,47:1, sur #8b5cf6 = 4,2:1, sur #d946ef = 3,5:1 — sous le seuil AA de 4,5:1 sur toute la course, de très peu au repos (indigo → violet), nettement au survol (violet → fuchsia). Foncez chaque arrêt d'un cran : #4f46e5, #7c3aed, #c026d3 donnent 6,3:1, 5,7:1 et 4,7:1. Un libellé de 18 px gras (seuil 3:1) passe aussi avec les couleurs d'origine.@media (prefers-reduced-motion: reduce) { .btn-gradient-shift { transition: none } } — les deux états restent, le passage devient instantané. Le mouvement est de toute façon borné : 3 px et 500 ms, déclenché par l'utilisateur, jamais en boucle.:hover n'existe à la navigation Tab. Déclarez .btn-gradient-shift:focus-visible avec les trois mêmes déclarations que le survol pour que le focus glisse et soulève comme la souris. Le code écrit border: none sans toucher à outline : l'anneau de focus natif reste et n'est pas rogné par overflow: hidden.:hover reste collé après un tap (le bouton demeure soulevé, sur sa moitié fuchsia, jusqu'au toucher suivant) ; enveloppez la règle de survol dans @media (hover: hover). Cible ≈ 50 px de haut, au-dessus du minimum de 44 px.#6366f1 sur #0a0a0f = 4,4:1) comme d'un fond blanc (3,5:1 au minimum, au-dessus du seuil 3:1 pour le contour d'un composant). Aucun contenu généré, aucun changement de libellé : le nom accessible est le texte, et le survol ne porte aucune information que la couleur seule aurait à transmettre.Requiert linear-gradient() non préfixé, background-size et la transition CSS de background-position, transform et box-shadow — tous les navigateurs depuis 2013. Aucun JavaScript, zéro dépendance.
Sans transitions, les deux états s'appliquent instantanément : la fenêtre saute de la moitié indigo à la moitié fuchsia, le bouton reste utilisable. Sans dégradés (navigateurs antérieurs à 2013), la déclaration background entière est ignorée et le bouton n'a plus de fond du tout — texte blanc sur la page : ajoutez background-color: #6366f1 juste avant le raccourci si vous devez servir ces navigateurs.
Copiez les trois blocs dans votre page. Aucune dépendance.
<button class="demo-btn btn-gradient-shift">Gradient Shift</button>
.demo-btn {
padding: 16px 32px;
font-size: 1rem;
font-weight: 600;
border-width: medium;
border-style: none;
border-color: currentcolor;
border-image: none;
border-radius: 12px;
cursor: pointer;
font-family: inherit;
position: relative;
overflow: hidden;
}
.btn-gradient-shift {
background: linear-gradient(135deg, rgb(99, 102, 241), rgb(139, 92, 246), rgb(217, 70, 239)) 0% 0% / 200% 200%;
color: white;
transition: 0.5s;
}
.btn-gradient-shift:hover {
background-position: 100% 100%;
transform: translateY(-3px);
box-shadow: rgba(99, 102, 241, 0.4) 0px 15px 35px;
}
Options passées à l'API ou attributs data-* :
| Option / propriété | Défaut | Effet |
|---|---|---|
Arrêts de couleur (CSS — linear-gradient(135deg, …)) |
#6366f1, #8b5cf6, #d946ef | Le 1er et le 2e arrêt font le repos, le 2e et le 3e le survol. Pour un texte blanc AA sur toute la course : #4f46e5, #7c3aed, #c026d3. Deux arrêts suffisent pour un glissement bicolore. |
background-size (CSS — / 200% 200% dans le raccourci) |
200% 200% | Part du dégradé cachée, donc course du glissement. 150% = trajet plus court, les deux moitiés se recouvrent ; 300% = grande course, ajoutez un 4e arrêt pour ne pas étirer les couleurs. À 100%, plus rien ne bouge. |
| background-position au survol (CSS — :hover) | 100% 100% | Point d'arrivée de la fenêtre. 100% 0% glisse horizontalement, 0% 100% verticalement — accordez-le à l'angle du dégradé pour que le mouvement suive les couleurs. |
| transition (CSS — .btn-gradient-shift) | 0.5s (all, ease) | Durée du glissement, du soulèvement et du halo — et du retour au repos. .3s = vif ; .8s = lent, presque liquide. Limitez à background-position, transform, box-shadow pour ne pas animer un changement de couleur de texte avec la même courbe. |
| translateY (CSS — :hover) | -3px | Soulèvement. 0 pour ne garder que le glissement de couleur ; -5px avec un halo plus long pour un bouton qui décolle. |
| box-shadow (CSS — :hover) | 0 15px 35px rgba(99, 102, 241, .4) | Halo indigo au survol, 50 px de portée sous le bouton. Gardez la couleur du 1er arrêt ; réduisez à 0 8px 20px dans une carte serrée, et vérifiez qu'aucun parent en overflow: hidden ne le coupe. |
Angle (CSS — 135deg) |
135deg | Direction de la rampe. La position 100% 100% suit la diagonale, le glissement paraît donc « dans le sens » des couleurs. 90deg + position 100% 0% = balayage horizontal gauche → droite. |
Parce qu'un linear-gradient() est une image : le navigateur ne sait pas interpoler entre deux images, il bascule de l'une à l'autre au milieu de la transition. Deux issues : celle du code — peindre le dégradé en 200% et faire glisser background-position, une longueur ordinaire, ce qui marche partout depuis 2013 — ou déclarer chaque couleur en propriété personnalisée enregistrée par @property (syntax: '<color>') et animer ces variables, ce qui fait réellement changer les arrêts mais suppose Chrome 85+, Safari 16.4+ et Firefox 128+.
Oui, avec une animation à la place de la transition : @keyframes shift { to { background-position: 100% 100% } } et animation: shift 4s ease-in-out infinite alternate sur .btn-gradient-shift. Le 200% reste la course ; alternate évite le saut au retour. Gardez la règle :hover pour le soulèvement et le halo, et coupez l'animation sous prefers-reduced-motion: reduce — un dégradé qui bouge en permanence gêne bien plus qu'un glissement au survol.
Trois causes, dans l'ordre : une règle plus tardive redéclare background en raccourci et remet background-size à auto — la fenêtre fait alors la taille du bouton et la position n'a plus rien à faire glisser (vérifiez la valeur calculée : 200% 200%) ; un reset * { transition: none } ou une classe utilitaire écrase la transition ; ou le survol est simulé par un parent qui change une classe d'un coup. Si background-size et transition sont bien calculés à 200% 200% et 0.5s, le glissement fonctionne.