Scroll✨ Premium

Text Reveal

Quatre blocs titre + sous-titre dans une boîte de 280 px : chaque mot (1,5 rem, graisse 800) part à translateY(100 %) sous une ligne en overflow: clip et remonte sur les 40 % de son entrée dans la boîte — 11 px de défilement —, puis son sous-titre passe de 0 à 1 sur les 10 → 50 % de sa propre entrée, 37 px plus bas. Deux animations CSS sur animation-timeline: view(), zéro JavaScript.

CSSTextReveal

Mis à jour le

Cet effet fait partie d'Effect.Labs — 811 effets vanilla, une partie gratuite, une partie premium. Scroll comprend 70 effets, dont 12 gratuits. Découvrir la catégorie →

3 exemples d'usage

Salles d'une exposition — audioguide web sur smartphone d'un musée — Text Reveal exemple 1

① Salles d'une exposition — audioguide web sur smartphone d'un musée

QuandPage de l'audioguide ouverte sur le téléphone du visiteur : Antiquités, Cabinet des dessins, Verrières, Sculptures, Réserves — chaque nom de salle sort de sa ligne quand le visiteur descend, suivi de sa phrase de présentation.
PourquoiLe nom de salle émerge net d'un masque, comme d'une plaque gravée, puis la ligne de détail suit : la hiérarchie titre → détail est codée dans les deux plages et dans les 36 px qui séparent leurs entrées. fx-0569 éclaire des mots en place, sans ce temps de retard ; un fondu global (fx-0535) montrerait nom et phrase d'un bloc.
RéglagesTéléphone de 250 × 340 px, boîte de 262 px sous l'en-tête, plateau en height: auto avec 110 px de marge basse (course 372 px), mots à 20 px, sous-titres à 11,5 px en blanc à 55 %, étiquette « Salle n » statique au-dessus de chaque ligne ; plages élargies à entry 0% entry 100% (25 px de course par mot, 16 par sous-titre), les 40 % du code vendu étant trop brefs pour une capture. Le défilement automatique est un artifice de démonstration.
Épreuves d'un triathlon — page résultats d'un organisateur sportif — Text Reveal exemple 2

② Épreuves d'un triathlon — page résultats d'un organisateur sportif

QuandOnglet « Épreuves » de la page de résultats : Natation, Vélo, Course à pied, puis Arrivée, chacune en capitales de 44 px sortant de sa ligne, avec dessous la distance et le meilleur temps de l'année.
PourquoiTrois mots courts et forts : le masque de ligne rend le mouvement propre (rien ne dépasse au-dessus de la ligne pendant la montée), et le sous-titre chiffré arrive après le mot ; un fondu global (fx-0535) montrerait mot et chiffres d'un bloc.
RéglagesBoîte de 302 px sous une barre de 58 px, mots en capitales à 44 px graisse 900 et letter-spacing: -.03em, sous-titres à 13 px en blanc à 70 % avec le temps en <b> couleur #5eead4, quatre blocs, marge basse de 150 px (course 326 px), plages entry 0% entry 100% (45 px de course par mot).
Manchettes d'un journal étudiant en ligne — page d'accueil éditoriale — Text Reveal exemple 3

③ Manchettes d'un journal étudiant en ligne — page d'accueil éditoriale

QuandUne du journal sur fond papier : quatre manchettes (Campus, Culture, Sport, Débat) en 1,5 rem sortent de leur ligne l'une après l'autre au défilement, chacune suivie de son chapô et précédée de son numéro de page.
PourquoiUne manchette se compose : le titre d'abord, le chapô ensuite ; les deux plages décalées font ce montage, et le masque, qui porte ici le filet, fait monter chaque titre de sous son filet sans qu'il chevauche la manchette précédente. Des mots déjà en place qui s'allument (fx-0569) laisseraient le filet posé sur un titre immobile.
RéglagesFond #f4f1ea et texte sombre (mot #1a1a1a, chapô #3a3732) à la place du cadre noir, Georgia pour les deux, mot à 1,5 rem graisse 700, chapô à 13 px sur 440 px au plus, filet border-top: 1px solid #d9d4c8 posé sur la ligne-masque, boîte de 292 px, marge basse de 120 px (course 284 px), plages entry 0% entry 100% (28 px par manchette).

Comment ça marche

Le HTML vendu : un cadre .demo-preview (flex centré, min-height: 300px, position: relative, fond #0a0a0f, texte blanc, font-family: sans-serif), la boîte .sdc-scroll-container (100% × 280px, overflow-y: auto, scroll-behavior: smooth, barre de 4 px stylée par ::-webkit-scrollbar, pouce violet à 40 %), le plateau .sdc-textreveal-content (900 px de haut, padding: 80px 24px, colonne flex, gap: 40px) et quatre div contenant chacun une ligne .sdc-textreveal-line (overflow: clip) qui masque un span.sdc-textreveal-word (inline-block, 1,5 rem = 24 px, graisse 800, blanc, 28 px de haut) et un p.sdc-textreveal-sub (0,82 rem = 13 px, blanc à 40 %, margin-top: 8px). Sous la boîte, span.sdc-scroll-hint « Scrollez ↓ » (absolu, 8 px du bas du cadre, 10,4 px, blanc à 30 %) pulse de .3 à .7 toutes les 2 s. Mesuré en page vierge : course 900 − 280 = 620 px, mots à 80, 184, 288 et 392 px du haut du plateau — un pas de 104 px, car la marge basse par défaut du p (13 px) s'ajoute aux 28 + 8 + 15 px du bloc et aux 40 px de gap. Aucun JavaScript, aucun id, aucune variable CSS, aucune erreur console.

Les deux textes partagent le même réglage : animation-timeline: view(), animation-duration: auto, animation-fill-mode: both, courbe linéaire. view() crée pour chaque élément une chronologie anonyme lue sur le conteneur de défilement le plus proche — ici la boîte — et graduée sur la traversée de son cadre par l'élément ; animation-range choisit le segment qui pilote les images-clés. Le mot part à translateY(100%) (100 % de sa hauteur, 28 px, sous sa ligne qui le rogne) et opacity: 0, et rejoint translateY(0) / 1 sur entry entry 40% : de l'instant où son bord haut touche le bas de la boîte jusqu'à 40 % de son entrée, soit 11,2 px de défilement. Mesuré par crans de 8 px dans Chromium 151 : le troisième mot est à 0 / 28 px à scrollTop 8, à .69 / 8,6 px à 16, à 1 / 0 à 24 ; le quatrième fait le même trajet entre 112 et 128. Le sous-titre n'a pas de transform de départ (le translateY(0) de sdcFadeIn ne change rien) : il passe de 0 à 1 sur entry 10% entry 50%, 40 % de ses 15 px, soit 6 px (mesuré .38 à 48, 1 à 56 pour le troisième ; .35 à 152, 1 à 160 pour le quatrième). Le décalage titre → détail vient de la géométrie plus que des pourcentages : le sous-titre entre dans la boîte 36 px après le mot (28 px de mot + 8 px de marge), et ses 10 % n'ajoutent que 1,5 px. Passé scrollTop 160, tout est visible ; il reste 460 px de course vide.

Jusqu'au 30 septembre 2026, la ligne était en overflow: hidden, et le masque ne s'est jamais ouvert : un élément en overflow: hidden est un conteneur de défilement, donc view() s'accrochait à la ligne elle-même, dont le mot remplit le cadre dès le départ. Mesuré sur ce code : getAnimations()[0].timeline.source = .sdc-textreveal-line, animation finished figée à 20 %, les quatre mots à opacité 1 et sans transform au repos — même celui posé à 392 px, hors de la boîte. Seuls les sous-titres, enfants directs des blocs, se rattachaient à la boîte et apparaissaient. overflow: clip rogne à l'identique sans créer de conteneur de défilement : la source devient .sdc-scroll-container et le mot sort de sa ligne. Autres traits du code : rien n'est indexé par id, chaque mot porte sa propre chronologie, donc plusieurs copies cohabitent dans une page et un cinquième bloc s'ajoute sans CSS ; scroll-behavior: smooth ne lisse que les défilements programmés ; la police est le sans-serif du système (rien n'est chargé) ; et le champ JavaScript du code vendu est vide.

Accessibilité

  • prefers-reduced-motion absent du code : mesuré sous la préférence dans Chromium, le troisième mot passe toujours de 0 à 1 entre scrollTop 8 et 24, l'indice pulse (animation-play-state: running) et scroll-behavior reste smooth. Le mouvement suit le geste et ne cache rien de durable — un bloc entré dans la boîte reste affiché —, ce qui le range dans les animations déclenchées par l'interaction (WCAG 2.3.3). Pour un repli sans mouvement : @media (prefers-reduced-motion: reduce) { .sdc-textreveal-word, .sdc-textreveal-sub { animation: none; opacity: 1; transform: none } .sdc-scroll-hint { animation: none } .sdc-scroll-container { scroll-behavior: auto } }.
  • Clavier : mesuré, Tab donne le focus à la boîte sans tabindex dans Chromium et Firefox (flèche bas : 40 et 51 px, PageDown : 285 et 303 px — la révélation suit), pas dans WebKit (focus resté sur body, flèches sans effet). Ajoutez tabindex="0", un aria-label (« Quatre mots, défilement vertical ») et un style :focus-visible sur .sdc-scroll-container. Au doigt, le geste doit commencer dans la boîte ; overscroll-behavior: contain évite d'entraîner la page en bout de course.
  • Contraste : le mot blanc sur #0a0a0f mesure 19,8:1. Le sous-titre à 40 % de blanc vaut 3,8:1 à 13 px — sous les 4,5:1 exigés pour un texte de cette taille ; 60 % (rgba(255,255,255,.6)) donne 7,3:1. L'indice mesure 2,6:1 au repos, de 1,2:1 à 1,8:1 sous la pulsation (l'opacité de .3 à .7 se multiplie au blanc à 30 % de la couleur) : décoratif, posez-lui aria-hidden="true". Le fond #0a0a0f du cadre fait partie du code : sur une page blanche, retirez-le et le texte blanc disparaît (1:1) — changez alors les trois couleurs, comme la troisième scène sur papier clair.
  • Lecteurs d'écran et structure : opacity: 0 ne retire rien de l'arbre d'accessibilité, les huit textes sont lus dans l'ordre, avant comme après le défilement, et rien n'est annoncé au passage — il n'y a rien à annoncer. Le mot est un span dans un div, le sous-titre un p : aucun titre dans le plan de la page. Pour des noms de salle ou d'épreuve, mettez le mot dans un h2 ou h3 (la classe suffit, la balise est libre) et gardez le p. Le libellé « Scrollez ↓ » est écrit en français dans le HTML, quelle que soit la langue de la page.

Compatibilité navigateur

CSS seul : animation-timeline: view(), animation-duration: auto, animation-range avec les repères entry — les animations pilotées par le défilement, arrivées dans Chrome et Edge 115 (juillet 2023) et Safari 26 (septembre 2025). Firefox ne les rend dans aucune version : mesuré dans Firefox 153, CSS.supports('animation-timeline: view()') répond faux, animation-duration: auto est rejeté (durée calculée 0 s) et l'animation, finished sur une chronologie de document, applique sa dernière image-clé — les huit textes sont affichés à opacité 1, sans transform, dès le repos, et la boîte défile normalement (course 620 px). Un visiteur Firefox voit donc une liste statique et complète, sans le glissement. ::-webkit-scrollbar est ignoré par Firefox (barre native). Zéro dépendance, zéro script.

Chrome 115+✓ Complet
Edge 115+✓ Complet
Safari 26+✓ Complet (mesuré dans WebKit 26.5 : mêmes valeurs que Chromium)
Firefox (toutes versions)✓ Statique : tout le texte affiché, aucun glissement
Mobile iOS 26+✓ Complet (défilement au doigt dans la boîte)
Android Chrome 115+✓ Complet

Là où animation-timeline et animation-duration: auto sont inconnus (Firefox, Safari avant 26, Chrome avant 115), les deux déclarations tombent, l'animation dure 0 s et animation-fill-mode: both la fige sur sa dernière image-clé : opacité 1, translateY(0). Le code n'a pas de bloc @supports et n'en a pas besoin, parce que l'état final est l'état lisible ; il en faudrait un — @supports not (animation-timeline: view()) { … } — si vous inversiez les images-clés (texte qui s'efface) ou si la fin de sdcTextReveal cessait d'être l'état de lecture. Sans overflow: clip (Chrome avant 90, Firefox avant 81, Safari avant 16), la ligne ne rogne plus rien, mais aucun mot n'y est translaté : rien ne change à l'écran.

Le code

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

index.html — structure
<div class="demo-preview">
  <div class="sdc-scroll-container">
    <div class="sdc-textreveal-content">
      <div>
        <div class="sdc-textreveal-line">
          <span class="sdc-textreveal-word">…</span>
        </div>
        <p class="sdc-textreveal-sub">…</p>
      </div>
      <div>
        <div class="sdc-textreveal-line">
          <span class="sdc-textreveal-word">…</span>
        </div>
        <p class="sdc-textreveal-sub">…</p>
      </div>
      <div>
        <div class="sdc-textreveal-line">
          <span class="sdc-textreveal-word">…</span>
        </div>
        <p class="sdc-textreveal-sub">…</p>
      </div>
      <div>
        <div class="sdc-textreveal-line">
          <span class="sdc-textreveal-word">…</span>
        </div>
        <p class="sdc-textreveal-sub">…</p>
      </div>
    </div>
  </div>
  <span class="sdc-scroll-hint">…</span>
</div>
Débloquer le code complet — 9,90 € HT/mois

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

Personnaliser

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

Option / propriétéDéfautEffet
Plage du mot (CSS — .sdc-textreveal-word { animation-range: entry entry 40% }) entry 0 % → entry 40 % (11,2 px pour un mot de 28 px) Les pourcentages sont ceux de l'entrée du mot dans la boîte, donc proportionnels à sa hauteur, pas à celle de la boîte. entry 0% entry 100% étire la sortie sur toute l'entrée (28 px, le réglage des trois scènes) ; entry 0% cover 30% la prolonge jusqu'à ce que le mot ait gravi 30 % de la boîte (environ 92 px).
Plage du sous-titre (CSS — .sdc-textreveal-sub { animation-range: entry 10% entry 50% }) entry 10 % → entry 50 % (6 px pour 15 px de haut) Le retard sur le mot vient surtout des 36 px qui séparent leurs entrées ; les 10 % n'ajoutent que 1,5 px. Pour un vrai temps mort, retardez le début (entry 100% cover 30%) ou augmentez margin-top.
Départ du mot (CSS — transform: translateY(100%) et opacity: 0) 100 % de sa hauteur (28 px), invisible Le mot part entièrement sous sa ligne. translateY(60%) le laisse dépasser d'un tiers avant le défilement ; opacity: 1 dans la règle de base donne une sortie de masque pure, sans fondu — l'image-clé finale reste valable.
Boîte et plateau (CSS — .sdc-scroll-container { height: 280px }, .sdc-textreveal-content { height: 900px }) 280 px / 900 px (course 620 px, tout révélé à 160 px) Le plateau est fixé à 900 px quel que soit le contenu : 460 px de course vide après le dernier bloc. height: auto avec un padding-bottom d'au moins la moitié de la boîte laisse le dernier bloc entrer complètement (les scènes : 110 à 150 px).
Taille et couleurs (CSS — font-size: 1.5rem, color: #fff ; .sdc-textreveal-sub : .82rem, rgba(255,255,255,.4)) 24 px / 800 / blanc ; 13 px / blanc à 40 % La plage suit la hauteur du mot : à 44 px (scène 2), les 40 % font 18 px de course. Le sous-titre à 40 % vaut 3,8:1 sur #0a0a0f ; 60 % passe à 7,3:1. Sur fond clair, changez les trois couleurs et retirez le fond du cadre.
Masque de ligne (CSS — .sdc-textreveal-line { overflow: clip }) clip À garder tel quel : hidden ferait de la ligne un conteneur de défilement et view() s'y rattacherait — les mots ne bougeraient plus (c'était le défaut du code avant le 30/09/2026). La ligne accepte un filet (border-top, scène 3) ou un padding-top sans rien casser.
Indice et barre (CSS — .sdc-scroll-hint, ::-webkit-scrollbar) « Scrollez ↓ » à 8 px du bas, barre de 4 px L'indice s'accroche au cadre .demo-preview (position: relative) : sans ce cadre, il tombe au bas de la page — supprimez le span et la @keyframes sdcHintPulse. La barre ne concerne que Chrome et Safari ; scrollbar-width: thin couvre Firefox.

FAQ

C'est le symptôme d'une ligne en overflow: hidden — le code vendu jusqu'au 30 septembre 2026, et encore la copie affichée dans la page catégorie. Un élément en overflow: hidden est un conteneur de défilement ; view() prend le plus proche, donc la ligne, où le mot occupe tout le cadre : l'animation est terminée avant le premier geste (mesuré : source de la chronologie = .sdc-textreveal-line, état finished figé à 20 %, quatre mots à opacité 1 au repos). La règle vaut pour tout ancêtre entre le mot et la boîte : une carte en overflow: hidden, un accordéon, un carrousel captent la chronologie de la même façon. Remplacez par overflow: clip (ou clip-path: inset(0)), qui rogne sans créer de conteneur, et vérifiez avec el.getAnimations()[0].timeline.source que la source est bien la boîte.
Parce que animation-range: entry entry 40% est mesuré sur l'entrée du mot, c'est-à-dire sur sa propre hauteur : 40 % de 28 px font 11,2 px de défilement, et 6 px pour le sous-titre. Un cran de molette de 100 px les traverse en une ou deux images ; au pavé tactile ou au doigt, le glissement se voit. Mesuré par pas de 8 px : 0 → .69 → 1 sur trois relevés. Pour l'étirer, élargissez la plage (entry 0% entry 100% : 28 px, le choix des trois scènes ; entry 0% cover 30% : environ 92 px, le mot finit de sortir alors qu'il est déjà bien dans la boîte) ou augmentez la taille du mot — la plage grandit avec lui. Ne touchez pas à animation-duration: auto : avec une chronologie de défilement, c'est la plage qui tient lieu de durée.
Le moteur est le même — animation-timeline: view(), animation-duration: auto, animation-range, zéro JavaScript, Firefox à plat dans les deux cas — mais pas le geste. fx-0569 aligne 43 mots inline-block dans un paragraphe de 300 px et n'anime que leur color : de blanc à 15 % à #e0e7ff (les six accents de violet à 20 % à #a78bfa) sur entry cover 40%, une seule plage pour tous. Les mots sont en place dès le départ et s'allument en glissant vers le haut de la boîte — une lecture qui s'éclaire. fx-0560 travaille par paire : un mot qui se déplace (translateY(100%) → 0) derrière un masque de ligne, puis un sous-titre qui apparaît sur une seconde plage, 36 px plus bas. Il fait quatre titres avec leur détail, là où fx-0569 fait un texte courant. Prenez fx-0569 pour un paragraphe à lire, fx-0560 pour une liste de titres courts que chaque détail suit.