Fill Slide Up
Bouton contour violet clair : au survol, un pseudo-élément dégradé monte du bas et remplit la boîte en 600 ms sur une courbe ease-in-out pendant que le texte passe au blanc — CSS seul, avec un clic qui saute sans transition.
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



Comment ça marche
Au repos, .btn-fill-slide est creux : background: transparent, border: 2px solid #a78bfa, color: #a78bfa. Il porte position: relative et z-index: 1 — le contexte d'empilement qui permet à son ::after en z-index: -1 de se peindre entre le fond du bouton et son texte, au lieu de passer derrière la page.
Le remplissage est ce ::after : position: absolute; bottom: 0; left: 0; width: 100%; height: 0, fond linear-gradient(135deg, #a78bfa, #8b5cf6), border-radius: 10px (le rayon intérieur : 12 px du bouton − 2 px de bordure). Au :hover, height passe à 100% — de 0 à 50 px sur le bouton de démonstration (54 px moins les deux bordures) — en .6s cubic-bezier(.65, 0, .35, 1), une courbe ease-in-out quartique : lente au départ, rapide au milieu, freinée à l'arrivée. overflow: hidden sur .demo-btn rogne le pseudo-élément aux coins arrondis.
Le texte suit la même courbe et la même durée : transition: color .6s, de #a78bfa à #fff. Mesuré dans Chromium à 300 ms : le remplissage atteint 57 % de la hauteur et le texte vaut #dacefd — un violet très pâle posé sur un fond violet, contraste 1,8:1. Comme les lettres occupent le tiers central de la hauteur, elles sont recouvertes par le dégradé entre ≈ 230 et 400 ms, alors que le texte n'est pas encore blanc : le libellé est illisible pendant environ 150 ms à chaque survol.
Au :active, transform: scale(.95). Mais la transition ne porte que sur color (et height pour le pseudo-élément) : la compression est instantanée, sans glissement — mesuré à +20 ms, l'échelle est déjà à 0,95. Le relâchement est tout aussi sec. Ajoutez transform .15s à la liste si vous voulez un clic amorti.
Accessibilité
- Contraste au repos :
#a78bfasur#0a0a0f= 7,3:1, niveau AAA. Au survol, contraste insuffisant : texte blanc sur le dégradé#a78bfa → #8b5cf6= 2,7:1 et 4,2:1, sous le seuil AA de 4,5:1. Assombrissez le remplissage —linear-gradient(135deg, #7c3aed, #6d28d9)donne 5,7:1 et 7,1:1 — en gardant bordure et texte de repos en#a78bfa. - Lisibilité pendant la transition : le texte traverse 150 ms d'illisibilité (1,2 à 1,8:1) quand le dégradé le recouvre avant qu'il soit blanc. Donnez au texte une transition plus courte que le remplissage (
transition: color .2s, ou.25savec un délai de.15s) pour qu'il soit blanc quand la vague l'atteint. - Fond sombre obligatoire : sur une page claire,
#a78bfasur blanc = 2,7:1 au repos. Pour un thème clair, prenez#6d28d9pour la bordure et le texte de repos. - prefers-reduced-motion absent du code : le remplissage est un mouvement de 50 px sur 600 ms. Ajoutez
@media (prefers-reduced-motion: reduce) { .btn-fill-slide, .btn-fill-slide::after { transition: none } }— le bouton bascule d'un coup du contour au plein, texte blanc compris. - Clavier et tactile : pas de
:hoverau clavier — dupliquez les deux règles de survol sous:focus-visibleet:focus-visible::after; l'outlinenatif est conservé. Sur iOS l'état rempli reste collé après un tap (@media (hover: hover)). Cible ≈ 54 px de haut, au-dessus du minimum de 44 px.
Compatibilité navigateur
Requiert les transitions CSS sur color et height avec cubic-bezier(), un pseudo-élément positionné et z-index négatif — tous les navigateurs depuis 2012. Aucun JavaScript, zéro dépendance.
Sans transitions, le remplissage apparaît d'un coup au survol, texte blanc compris : le bouton reste utilisable et lisible, seule la montée de 600 ms disparaît.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
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éfaut | Effet |
|---|---|---|
| transition-duration (CSS — .btn-fill-slide et ::after) | .6s | Durée du remplissage et du changement de couleur du texte. .35s = réactif ; .9s = très lent, à réserver à un gros bouton isolé. |
| cubic-bezier(.65, 0, .35, 1) (CSS — transition) | ease-in-out quartique | Départ et arrivée lents, milieu rapide. cubic-bezier(.22, 1, .36, 1) (ease-out) fait démarrer la vague plus vite ; linear donne un remplissage mécanique. |
| Direction (CSS — ::after : bottom / height) | du bas vers le haut | Remplacez bottom: 0 par top: 0 pour descendre ; pour aller de gauche à droite, animez width (0 → 100 %) avec height: 100% fixe. |
| background (CSS — ::after) | linear-gradient(135deg, #a78bfa, #8b5cf6) | Couleur du remplissage. Pour un contraste AA avec le texte blanc : #7c3aed → #6d28d9. Une couleur unie fonctionne aussi. |
| color (CSS — :hover) | #fff | Couleur du texte une fois rempli. Un texte sombre (#1e1b4b) sur le violet clair d'origine donne 5,9:1 sans changer le dégradé. |
| border / color (CSS — .btn-fill-slide) | 2px solid #a78bfa / #a78bfa | Contour et texte au repos. À aligner sur la couleur claire du dégradé pour que la vague semble sortir de la bordure. Sur fond clair, foncez les deux. |
| transform (CSS — :active) | scale(.95), sans transition | Compression au clic, instantanée. Ajoutez transform .15s à la liste des transitions du bouton pour l'amortir, ou retirez la règle. |
FAQ
transition: color .2s), un texte retardé puis rapide (transition: color .25s .15s) pour qu'il devienne blanc au moment où la vague l'atteint, ou un remplissage plus sombre (#7c3aed → #6d28d9), qui contraste avec le violet pâle intermédiaire comme avec le blanc final.left: 0; top: 0; height: 100% et animez width: 0 → 100%. Depuis le centre : left: 50%; width: 0 avec translateX(-50%), puis width: 100% au survol — ou, plus léger pour le rendu, transform: scaleX(0) → scaleX(1) avec transform-origin: center, qui ne déclenche pas de recalcul de mise en page.z-index: -1. Sans contexte d'empilement propre au bouton, il irait se peindre derrière le fond de la page et le remplissage serait invisible. position: relative; z-index: 1 crée ce contexte : le ::after se peint au-dessus du fond transparent du bouton mais sous son texte. Si vous placez le bouton dans un parent qui a déjà isolation: isolate, le z-index: 1 reste nécessaire.