Boutons✨ Premium

Slide Reveal

Au survol, le libellé glisse vers le haut de sa propre hauteur en 400 ms et un second texte, vert, écrit dans l'attribut data-text, prend sa place. Une condition à vérifier : la zone de découpe doit avoir la hauteur du libellé — dans le code livré, les deux lignes restent visibles.

CSSTextReveal

Mis à jour le

Cet effet fait partie d'Effect.Labs — 840 effets vanilla, une partie gratuite, une partie premium. Boutons comprend 27 effets, dont 2 gratuits. Découvrir la catégorie →

3 exemples d'usage

Télécharger l'app — carte de téléchargement — Slide Reveal exemple 1

① Télécharger l'app — carte de téléchargement

QuandCarte d'application : icône, nom, note, un bouton pleine largeur.
PourquoiLe survol révèle la plateforme et la version — un détail utile au moment de décider, sans surcharger le bouton au repos. Le cas d'usage figurait sur l'ancienne fiche.
Réglagesdata-text="macOS · v3.2", second libellé en #a5b4fc, left: 0; right: 0; text-align: center pour le centrer.
S'abonner — champ de newsletter — Slide Reveal exemple 2

② S'abonner — champ de newsletter

QuandBloc d'inscription : un champ e-mail, un bouton d'envoi dessous.
PourquoiLe second texte rassure (« 0 spam ») juste avant l'engagement : c'est la promesse au moment du doute, glissée dans le bouton plutôt qu'en note de bas de formulaire. L'ancienne fiche listait le cas d'usage du formulaire.
Réglagesdata-text="0 spam", courbe cubic-bezier(.2, .8, .2, 1), .3s.
Voir la bande-annonce — hero d'un jeu ou d'un film — Slide Reveal exemple 3

③ Voir la bande-annonce — hero d'un jeu ou d'un film

QuandHero sombre : titre, date de sortie, un bouton pour lancer la vidéo.
PourquoiLe survol révèle la durée (« ▶ 2:14 ») : l'utilisateur sait à quoi il s'engage avant de cliquer. Le vert sur fond sombre reste très lisible même sur un visuel chargé.
Réglagesdata-text="▶ 2:14", padding: 0 40px avec line-height: 56px, font-size: 17px.

Comment ça marche

Le HTML porte les deux libellés en un seul élément : <span class="btn-text" data-text="Let's Go!">Hover Me</span>. Le premier est le texte du span ; le second est généré par CSS : .btn-text::after { content: attr(data-text); position: absolute; left: 0; top: 100%; color: #22c55e } — il est posé juste sous le premier, à une hauteur de ligne (18 px mesurés pour 16 px de texte en line-height: normal), aligné à gauche. Le span est display: inline-block; position: relative pour servir de repère.

Au :hover, .btn-text reçoit transform: translateY(-100%) avec transition: transform .4s cubic-bezier(.65, 0, .35, 1) — une courbe d'accélération-décélération symétrique (à mi-temps, mi-distance). Le span monte de sa hauteur et emporte son ::after : le texte vert arrive exactement là où était le blanc. Seul transform est animé — couche composée, aucun recalcul de mise en page. À la sortie, même trajet en sens inverse.

L'échange suppose que ce qui sort du cadre soit caché. Le code compte sur overflow: hidden, déclaré deux fois — sur .demo-btn et sur .btn-slide-reveal. Or la zone de découpe d'un bouton est sa boîte de padding : 16 px au-dessus et au-dessous du texte. Les libellés ne bougent que de 18 px. Mesuré dans Chromium sur le bouton livré (52 px de haut) : au repos, le texte vert est 18 px sous le blanc, dont 16 px à l'intérieur du padding — visible ; au survol, le blanc est remonté dans le padding supérieur — visible aussi. Le bouton livré se lit comme deux lignes, « Hover Me » au-dessus de « Let's Go! », au repos comme au survol : la paire glisse de 18 px, rien n'est révélé.

Il faut que la découpe ait la hauteur du libellé. Deux corrections. En CSS seul, sur le bouton : padding-top: 0; padding-bottom: 0; line-height: 50px — le span hérite d'une ligne de 50 px, top: 100% et translateY(-100%) valent 50 px, le texte reste centré et le bouton garde ses 52 px avec sa bordure. En structure : un span englobant display: inline-block; overflow: hidden; vertical-align: top autour de .btn-text, dont la découpe suit le texte quel que soit le padding. Les scènes de cette page utilisent la première ; vérifiez qu'une des deux accompagne le code que vous collez.

Accessibilité

  • Contraste : blanc sur #1e1e2e = 16,4:1 et vert #22c55e sur #1e1e2e = 7,2:1 — AAA pour les deux libellés. Le fond est opaque : la couleur de la page n'entre pas en jeu. Livré conforme.
  • Le second libellé est lu par les lecteurs d'écran : le texte généré par content: attr(data-text) entre dans le nom accessible dans Chrome, Firefox et Safari — le bouton s'annonce « Hover Me Let's Go! », les deux à la suite. Donnez au bouton un aria-label explicite (le libellé principal), ou faites du second texte une reformulation du premier plutôt qu'une information nouvelle : ce qui n'apparaît qu'au survol n'existe pas pour le clavier ni le tactile.
  • prefers-reduced-motion absent du code : @media (prefers-reduced-motion: reduce) { .btn-slide-reveal .btn-text { transition: none } } — l'échange devient instantané, sans glissement.
  • Clavier : aucun :hover au focus. .btn-slide-reveal:focus-visible .btn-text { transform: translateY(-100%) } reproduit l'échange à l'arrivée du focus. Le code ne retire pas outline : l'anneau natif reste, hors de la zone découpée.
  • Tactile : pas de survol ; sur iOS le second libellé reste affiché après un tap (@media (hover: hover)). Un libellé qui change au survol doit laisser le bouton identifiable par un nom stable (WCAG 3.2.4) : c'est l'aria-label qui le garantit. Cible 52 px de haut, au-dessus du minimum de 44 px.

Compatibilité navigateur

Requiert la transition CSS de transform, content: attr() sur un pseudo-élément et overflow: hidden — 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✓ Complet (second libellé collé après un tap)
Android Chrome✓ Complet (au tap)

Sans transitions, les deux libellés s'échangent instantanément au survol ; l'information est la même, le glissement manque.

Le code

Structure HTML à coller dans votre page (le CSS + JS sont inclus avec Premium) :

index.html — structure
<button class="demo-btn btn-slide-reveal">
  <span class="btn-text" data-text="Let's Go!">Hover Me</span>
</button>
Débloquer le code complet — 9,90 € TTC/mois

Le code complet HTML + CSS + JS de Slide Reveal, prêt à coller — et les 840 effets. Ou 299 € TTC une fois, accès à vie.

Personnaliser

Options passées à l'API ou attributs data-* :

Option / propriétéDéfautEffet
data-text (HTML — attribut du span) Let's Go! Le second libellé. Gardez-le de longueur proche du premier : le ::after est absolu dans le span, sa largeur disponible est celle du premier texte — un texte plus long passe à la ligne (mesuré : trois lignes pour « From $9 per month » sous « Pricing »). white-space: nowrap l'empêche, mais il dépassera alors à droite.
color: #22c55e (CSS — ::after) #22c55e Couleur du second libellé. inherit pour le même blanc ; une couleur d'accent pour marquer le changement d'état.
transition: transform .4s cubic-bezier(.65, 0, .35, 1) (CSS — .btn-text) .4s, accélération-décélération .25s : sec ; cubic-bezier(.34, 1.56, .64, 1) : le second texte dépasse et revient — le premier réapparaît alors brièvement par le haut.
top: 100% (CSS — ::after) 100 % (dessous) top: -100% avec translateY(100%) au survol : le second texte arrive par le haut et le premier descend.
left: 0 (CSS — ::after) aligné à gauche left: 0; right: 0; text-align: center centre un second libellé plus court sous le premier ; sans cela, il colle à gauche.
Zone de découpe (CSS — .btn-slide-reveal, correctif) padding 16px 32px (deux lignes visibles) padding: 0 32px; line-height: 50px : la découpe prend la hauteur du texte et l'échange fonctionne (voir Comment ça marche). Ou un span englobant en overflow: hidden.
background: #1e1e2e + border rgba(255,255,255,.1) (CSS — .btn-slide-reveal) gris-bleu sombre Fond opaque de votre choix. Sur un fond clair, revoyez les deux couleurs de texte : le vert #22c55e tombe à 2,3:1 sur blanc — #15803d donne 5,0:1.

FAQ

Si — mais la découpe livrée est la boîte de padding du bouton, 16 px plus haute et plus basse que le texte, alors que les libellés ne se déplacent que de 18 px : ce qui « sort » reste dans le padding, donc visible. Corrigez avec padding: 0 32px; line-height: 50px sur .btn-slide-reveal (la découpe a alors la hauteur de la ligne), ou enveloppez le span dans un conteneur display: inline-block; overflow: hidden; vertical-align: top.
Le ::after est positionné en absolu dans .btn-text : sa largeur disponible est celle du premier libellé. Plus long, il replie ses mots. Posez white-space: nowrap sur le ::after et choisissez des libellés de longueur voisine ; si le second est plus court, centrez-le avec left: 0; right: 0; text-align: center.
Les deux textes, à la suite : le contenu généré par content: attr(data-text) est intégré au nom accessible du bouton par les navigateurs récents — « Hover Me Let's Go! ». Deux remèdes : aria-label="Hover Me" sur le bouton, qui fixe le nom quel que soit l'état ; ou un second libellé qui reformule le premier au lieu d'apporter une information, pour que la lecture double reste cohérente.