Texte✨ Premium

Stroke Animation

Remplissage progressif gauche–droite d'un texte outlined via pseudo-élément et clip-path animé — 100 % CSS, zéro JavaScript requis.

CSSStrokeFill

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. Texte comprend 56 effets, dont 4 gratuits. Découvrir la catégorie →

3 exemples d'usage

Agence créative — Grand titre display — Stroke Animation exemple 1

① Agence créative — Grand titre display

QuandHero d'un portfolio ou d'un site d'agence, quand un seul mot résume l'identité visuelle de la marque sur un fond sombre.
PourquoiL'outline creux anime la révélation du mot comme un tampon d'encre qui s'appose — une signature mémorable qui n'écrase pas le reste de la composition car l'outline seul reste toujours visible.
RéglagesCouleur stroke/fill #c026d3 (fuchsia brand), font-size: 6rem; font-weight: 900, animation-duration: 3s, animation-direction: normal + animation-fill-mode: forwards + animation-iteration-count: 1 pour une révélation unique.
Splash screen — Nom de produit au démarrage — Stroke Animation exemple 2

② Splash screen — Nom de produit au démarrage

QuandÉcran d'attente pendant l'initialisation d'une application web ou mobile — le nom se révèle et se résorbe en boucle pendant le chargement.
PourquoiL'alternate en boucle crée une respiration visuelle vivante sans spinner tournant — un seul <code>&lt;span&gt;</code> CSS, aucune bibliothèque d'animation.
RéglagesCouleur stroke/fill #06b6d4 (cyan-500), font-size: 3.5rem; letter-spacing: 0.06em, animation-duration: 2.5s ease-in-out, direction alternate infinite (défaut conservé).
Fin de partie — Révélation dramatique du résultat — Stroke Animation exemple 3

③ Fin de partie — Révélation dramatique du résultat

QuandÉcran de résultat d'un quiz ou d'un jeu compétitif, quand le mot victorieux se dévoile après un suspense.
PourquoiLe wipe gauche–droite mime le dévoilement d'un résultat imprimé ; avec <code>direction: normal</code> et <code>fill-mode: forwards</code>, la révélation ne revient jamais en arrière — effet de verdict définitif.
RéglagesCouleur stroke/fill #f59e0b (amber-400), font-size: 4rem; font-weight: 900, animation-duration: 1.5s cubic-bezier(.4,0,.2,1), animation-iteration-count: 1, animation-fill-mode: forwards.

Comment ça marche

L'effet repose sur deux couches superposées : l'élément .text-stroke porte -webkit-text-stroke: 2px #6366f1 et -webkit-text-fill-color: transparent — le texte apparaît donc en outline creux. Un pseudo-élément ::before est généré par content: attr(data-text) et positionné en absolute sur left: 0; top: 0, formant une copie exacte du texte en couleur pleine par-dessus l'outline.

La révélation s'obtient par clip-path animé : ::before démarre à clip-path: inset(0 100% 0 0) (rognage 100 % depuis la droite — le texte rempli est entièrement masqué) et l'animation @keyframes strokeFill le fait progresser vers clip-path: inset(0) (aucun rognage — texte pleinement visible). Le résultat visuel est un wipe gauche–droite qui révèle progressivement la couleur à travers l'outline.

La propriété animation-direction: alternate inverse le cycle à chaque itération : le texte se remplit, puis se vide de droite à gauche, puis se remplit à nouveau. Passer à animation-direction: normal avec animation-iteration-count: 1 et animation-fill-mode: forwards produit une révélation unique, non répétée — le texte reste rempli à la fin.

Le JS embarqué définit une fonction helper splitChars(el) qui découpe le texte de l'élément en <span class="char"> individuels pour des animations caractère par caractère avec décalage. Elle n'est pas appelée au démarrage — l'animation par défaut s'applique au mot entier via CSS. La constante document.getElementById('fadeInText') retourne null dans la configuration fournie (pas d'id fadeInText dans le HTML) : aucun effet de bord JS à l'initialisation.

Accessibilité

  • prefers-reduced-motion absent : aucune media query n'est présente dans le code fourni — l'animation tourne inconditionnellement. Correctif recommandé : @media (prefers-reduced-motion: reduce) { .text-stroke::before { animation: none; clip-path: inset(0) } } (le texte reste visible, immobile).
  • Le texte est du contenu DOM réel (textContent de l'élément <span>) — lu nativement par les lecteurs d'écran sans attribut ARIA supplémentaire.
  • La couleur de remplissage #6366f1 sur fond #0a0a0f atteint un ratio de contraste ≈ 3,5:1 — conforme WCAG AA pour les grands textes (≥ 24 px / weight ≥ 700), insuffisant pour un corps de texte courant. Pendant l'état « outline seul », le contraste de l'outline fin peut être en-dessous du seuil.
  • Aucune interaction clavier — l'effet est 100 % CSS, aucun focus implicite généré.
  • Aucun aria-label ni role n'est posé sur l'élément. Ajouter un aria-label au wrapper si le texte est très stylisé ou si la couleur seule le rend ambigu (ex. texte sur fond complexe).

Compatibilité navigateur

S'appuie sur -webkit-text-stroke, -webkit-text-fill-color et clip-path: inset() — supportés dans tous les navigateurs modernes depuis 2019. La syntaxe -webkit- est conservée par convention mais fonctionne sans préfixe sur Firefox et Edge.

Chrome 88+✓ Complet
Firefox 90+✓ Complet
Safari 15+✓ Complet
Edge 88+✓ Complet
Mobile iOS✓ Complet
Android Chrome✓ Complet

Sans support de <code>-webkit-text-fill-color</code>, le texte s'affiche avec sa couleur CSS héritée (pas d'outline transparent). Sans <code>clip-path</code>, le pseudo-élément <code>::before</code> est entièrement visible dès le chargement — le texte reste lisible, l'animation de révélation n'a pas lieu.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
<div class="demo-preview">

  <!-- data-text doit correspondre exactement au textContent de l'élément
       (les deux sont lus par les lecteurs d'écran) -->
  <span
    class="demo-text text-stroke"
    data-text="VOTRE TEXTE"
  >VOTRE TEXTE</span>

</div>
🔒 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
-webkit-text-stroke sur .text-stroke 2px #6366f1 Épaisseur (px) et couleur (hex) de l'outline. 1px pour un trait fin, 4px pour un affichage très grand. La couleur peut différer du fill pour un effet bicolore.
-webkit-text-fill-color sur .text-stroke::before #6366f1 Couleur du remplissage. Doit généralement correspondre à la couleur de l'outline, mais peut être différente pour un effet intentionnel (ex. stroke blanc, fill doré).
animation-duration sur .text-stroke::before 2s Durée d'un demi-cycle (remplissage ou vidage). 1s = rapide et percutant, 4s = lent et cinématique.
animation-direction sur .text-stroke::before alternate Valeur normal pour un wipe unique gauche–droite sans retour. Combiner avec animation-iteration-count: 1 et animation-fill-mode: forwards.
animation-timing-function sur .text-stroke::before ease-in-out Courbe de vitesse du wipe. linear = progression régulière, cubic-bezier(.4,0,.2,1) = départ lent puis accélération dramatique.
font-size sur .demo-text 2.5rem Taille du texte. L'effet est plus lisible à partir de 2rem — en dessous, l'outline fine peut rendre la lecture difficile.
data-text sur l'élément STROKE Texte affiché ET dupliqué dans content: attr(data-text) sur le pseudo-élément. Doit correspondre au textContent — les deux sont lus par les outils d'accessibilité.
clip-path initial sur .text-stroke::before inset(0 100% 0 0) Définit le bord de départ du wipe. inset(0 0 0 100%) inverse la direction (révélation droite–gauche). inset(100% 0 0 0) produit un wipe de bas en haut.

FAQ

Oui, entièrement. L'animation de remplissage est 100 % CSS. Le JS inclus dans l'effet définit une fonction helper splitChars(el) pour animer les lettres une par une, mais elle n'est pas appelée au démarrage. Vous pouvez omettre ce bloc JS sans aucune conséquence sur l'animation de base.
Remplacez animation: 2s ease-in-out 0s infinite alternate par animation: 2s ease-in-out 0s 1 normal none forwards strokeFill. Les valeurs clés : 1 (une seule itération), normal (remplissage gauche→droite sans retour), forwards (le texte reste rempli à la fin de l'animation).
Oui, avec la fonction splitChars(el) fournie dans le JS : elle découpe le texte en <span class="char"> et retourne la NodeList. Appliquez ensuite un animation-delay croissant sur chaque .char via chars.forEach((c, i) => c.style.animationDelay = i * 0.12 + 's'). Ajoutez position: relative à .char pour que le ::before CSS se positionne correctement sur chaque lettre.