Wave Animation V2
Lettres en vague par décalage progressif de 100 ms : @keyframes waveV2 CSS pur, JS injecte les délais pour n'importe quel texte, zéro dépendance.
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



Comment ça marche
L'animation repose sur @keyframes waveV2 : un simple translateY(0) → translateY(−10 px) → translateY(0) sur 1 s en ease-in-out infini. Chaque lettre est un <span> avec display: inline-block — sans quoi transform n'a aucun effet sur les éléments inline.
L'effet de vague naît du décalage progressif entre les lettres : le script JS calcule animation-delay: 0,1 s × index et l'injecte en attribut style sur chaque <span> généré via "BOUNCE".split("").map((ch, i) => ...). Le CSS redéfinit également les délais via :nth-child(1..6) — un fallback si le JS est absent ou si les spans sont pré-construits dans le HTML.
L'IIFE JS partage son contexte avec d'autres effets de la même page (#waveText, #flipText, #scrambleTextHover) via des gardes séquentielles : si l'un des getElementById retourne null, la fonction sort immédiatement. Pour un usage isolé, les spans pré-construits dans le HTML avec les bons animation-delay inline suffisent — l'animation tourne alors 100 % CSS, sans JS.
Pour changer le texte animé, modifiez la chaîne "BOUNCE" dans le JS, ou pré-construisez vos <span> directement dans le HTML avec style="animation-delay: Ns". Au-delà de 6 lettres, seul le JS applique les délais corrects aux lettres suivantes — le CSS :nth-child ne couvre que les 6 premières.
Accessibilité
- ⚠️ prefers-reduced-motion absent du code : l'animation s'exécute inconditionnellement. En production, ajoutez
@media (prefers-reduced-motion: reduce) { .text-wave-v2 span { animation: none } }. - Pas d'
aria-labelsur le conteneur : les lecteurs d'écran peuvent lire lettre par lettre. Ajoutezaria-label="VOTRE TEXTE"sur le<span>parent etaria-hidden="true"sur chaque lettre enfant. - Contraste excellent : texte blanc (
#fff) sur fond sombre (#0a0a0f), ratio > 18:1, niveau WCAG AAA — valable pour toute couleur claire sur fond sombre. - Aucune interaction clavier ni focus — effet purement décoratif, aucun focus-management requis.
- Sans CSS, le texte reste visible à plat : les lettres s'affichent comme un mot continu, lisibilité intacte.
Compatibilité navigateur
CSS animation + transform: translateY et display: inline-block — supportés dans tous les navigateurs modernes. L'IIFE JS est du vanilla pur (getElementById, innerHTML, split).
Si JS absent ou en erreur, les <code><span></code> pré-construits dans le HTML gardent leurs <code>animation-delay</code> inline et continuent d'animer via CSS. Si CSS désactivé, le texte s'affiche à plat, lisible.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<span class="demo-text text-wave-v2" id="waveTextV2"
aria-label="BOUNCE">
<!-- 1 <span> par lettre — délai progressif de 0,1 s par rang -->
<span aria-hidden="true" style="animation-delay: 0s">B</span>
<span aria-hidden="true" style="animation-delay: 0.1s">O</span>
<span aria-hidden="true" style="animation-delay: 0.2s">U</span>
<span aria-hidden="true" style="animation-delay: 0.3s">N</span>
<span aria-hidden="true" style="animation-delay: 0.4s">C</span>
<span aria-hidden="true" style="animation-delay: 0.5s">E</span>
</span>
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 |
|---|---|---|
| translateY(−10px) dans @keyframes waveV2 | −10 px | Amplitude verticale : augmentez à −20 px pour une vague marquée, réduisez à −5 px pour un frémissement subtil. |
| animation: 1s ease-in-out … sur .text-wave-v2 span | 1 s | Durée d'un cycle complet. 0,6 s = vague rapide et nerveuse, 2 s = mouvement lent et fluide. |
| ease-in-out dans animation (timing-function) | ease-in-out | Courbe de vitesse de chaque lettre. Essayez cubic-bezier(.4,0,.6,1) pour un rebond plus prononcé. |
| 0.1 dans le JS (${.1*t}s) | 0,1 s | Délai inter-lettres (stagger). 0,05 s = vague rapide et serrée, 0,2 s = vague très étalée sur un long mot. |
| font-size: 2.5rem sur .demo-text | 2,5 rem | Taille du texte — la vague est plus spectaculaire sur de grands corps (4 rem+). Adaptez librement via CSS sur le parent. |
| font-weight: 800 sur .demo-text | 800 | Graisse — réduisez à 400–600 pour un titre éditorial léger, conservez 700–900 pour un effet graphique fort. |
| letter-spacing: −0.02em sur .demo-text | −0,02 em | Espacement des lettres. Passez à 0,08–0,15 em sur un texte court en majuscules pour aérer la vague. |
| color sur .demo-text ou son parent | hérité (#fff) | Couleur du texte — aucune variable CSS dédiée, modifiez via color CSS directement sur l'élément ou un parent. |
FAQ
split("") régénère les spans pour n'importe quelle longueur. Au-delà de 6 lettres, les délais :nth-child du CSS ne couvrent que les 6 premières — les suivantes n'ont pas de délai CSS. Si vous pré-construisez vos spans sans JS, ajoutez les animation-delay inline manuellement pour chaque lettre supplémentaire.infinite par 1 dans animation-iteration-count sur .text-wave-v2 span. Pour déclencher la vague au scroll, retirez la classe text-wave-v2 au chargement et ajoutez-la via un IntersectionObserver quand l'élément entre dans le viewport — la vague se joue une fois puis s'arrête.<span> pré-construits dans le HTML avec les animation-delay inline continuent d'animer en CSS pur même si le JS est absent. Seule la reconstruction dynamique du texte (innerHTML) est perdue. Pour un usage 100 % CSS, pré-construisez vos spans manuellement — c'est suffisant pour des textes courts et statiques.