Boutons✨ Premium

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.

CSSHoverFill

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

Voir mes projets — bouton secondaire d'un portfolio — Fill Slide Up exemple 1

① Voir mes projets — bouton secondaire d'un portfolio

QuandHero d'un portfolio ou d'une agence : un bouton plein pour le contact, un bouton contour pour les travaux.
PourquoiLe contour marque l'action secondaire ; le remplissage au survol lui donne autant de présence que le bouton principal au moment où l'on le vise. La courbe ease-in-out lente convient à un site qui vend de la maîtrise plutôt que de la vitesse.
RéglagesRemplissage #7c3aed → #6d28d9 pour le contraste, transition: color .2s .15s sur le texte, padding: 16px 30px.
Lire l'article — carte de blog — Fill Slide Up exemple 2

② Lire l'article — carte de blog

QuandListe d'articles : image, catégorie, titre, extrait et un bouton de lecture par carte.
PourquoiUn bouton contour n'alourdit pas une grille de cartes ; le remplissage qui monte au survol désigne la carte visée sans changer sa taille. Sur un petit bouton, le trajet de 44 px reste visible.
Réglagespadding: 11px 18px, 13,5 px, border-radius: 8px (pseudo-élément à 6px), durée .45s.
Envoyer le message — formulaire de contact — Fill Slide Up exemple 3

③ Envoyer le message — formulaire de contact

QuandFormulaire court : nom, e-mail, message, un bouton d'envoi aligné à droite.
PourquoiLe remplissage progressif dit « prêt à partir » sans agressivité ; il fonctionne aussi comme état de survol d'un bouton désactivé qui vient de s'activer. Le clic sec (scale(.95) sans transition) confirme l'envoi.
RéglagesAjoutez transform .15s à la transition pour amortir le clic, padding: 14px 28px, dégradé sombre pour le contraste.

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 : #a78bfa sur #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 .25s avec un délai de .15s) pour qu'il soit blanc quand la vague l'atteint.
  • Fond sombre obligatoire : sur une page claire, #a78bfa sur blanc = 2,7:1 au repos. Pour un thème clair, prenez #6d28d9 pour 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 :hover au clavier — dupliquez les deux règles de survol sous :focus-visible et :focus-visible::after ; l'outline natif 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.

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, 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) :

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
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

Le dégradé recouvre les lettres vers 230–400 ms alors que le texte, qui va du violet clair au blanc en 600 ms, est encore violet pâle : contraste 1,2 à 1,8:1. Trois remèdes : un texte plus rapide (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.
De gauche à droite : gardez 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.
Le pseudo-élément a 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.