Wave Effect
Chaque lettre ondule verticalement avec un délai CSS progressif — le JS découpe le texte en spans à la volée pour animer chaque caractère indépendamment.
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
Le IIFE cible document.getElementById('waveText') et remplace son innerHTML par la chaîne "WAVE" découpée lettre à lettre : chaque caractère devient un <span> portant style="animation-delay: Xs" calculé comme 0,1 × index secondes. Le texte source est hardcodé dans le script ; pour l’adapter, remplacer "WAVE" par e.textContent.
La règle CSS .text-wave span applique animation: 1s ease-in-out 0s infinite wave et, point essentiel, display: inline-block : sans cette valeur, transform: translateY() n’a aucun effet sur des éléments inline. Le keyframe @keyframes wave fait passer chaque lettre de translateY(0) à translateY(-15px) à mi-durée, puis revient à zéro, créant une oscillation sinusoïdale verticale bouclée à l’infini.
Le décalage progressif crée l’illusion de vague : la lettre 0 monte la première, la lettre 1 suit 100 ms plus tard, et ainsi de suite. Avec un mot de 4 lettres, la crête parcourt la largeur totale en 300 ms avant que la première lettre ne recommence — la vague semble se déplacer de gauche à droite en continu.
Le fichier CSS embarque deux variantes supplémentaires : .text-wave-v2 avec @keyframes waveV2 (amplitude −10 px, délais nth-child fixes pour 6 enfants) et .text-wave-continuous (durée 2 s). Le même IIFE initialise en parallèle waveTextV2 (texte « BOUNCE »), flipText et un effet de scramble au survol sur scrambleTextHover — avec retour anticipé si l’élément est absent du DOM.
Accessibilité
- prefers-reduced-motion absent : aucune media query ni vérification JS ne coupe l’animation si le système signale cette préférence. Recommandation : ajouter
@media (prefers-reduced-motion: reduce) { .text-wave span, .text-wave-v2 span { animation: none; } }. - Les
<span>enfants injectés par le JS ne portent pas d’attributaria-hidden— le contenu textuel reste intact dans l’arbre d’accessibilité et lisible par les lecteurs d’écran. - Aucune interaction clavier ni focus géré par l’effet : l’animation est purement décorative/présentative.
- Le contraste texte/fond n’est pas défini par l’effet ; il dépend entièrement du contexte d’intégration. Vérifier un ratio WCAG AA ≥ 4,5:1 pour les textes normaux.
- Pas de scintillement rapide : la fréquence d’oscillation est ~1 Hz, bien sous le seuil de 3 Hz des crises photosensibles (WCAG 2.3.1).
Compatibilité navigateur
Nécessite uniquement des animations CSS (@keyframes, transform) et une manipulation DOM basique — support universel dans les navigateurs modernes.
Si le JS est désactivé, le texte reste intact dans son conteneur (lisible) mais les <code><span></code> individuels ne sont pas créés — l’animation ne se déclenche pas. Aucune erreur JS, aucune dépendance réseau.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<span class="demo-text text-wave" id="waveText">
<!-- Le JS remplace le texte par un <span style="animation-delay: Xs"> par lettre -->
<span style="animation-delay: 0s">V</span>
<span style="animation-delay: 0.1s">A</span>
<span style="animation-delay: 0.2s">G</span>
<span style="animation-delay: 0.3s">U</span>
<span style="animation-delay: 0.4s">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 |
|---|---|---|
| Amplitude de l’onde (@keyframes wave, 50%) | -15px | Valeur translateY au point médian — -6 px pour un effet subtil, -30 px pour un rebond ample. |
| Durée d’animation (.text-wave span, animation) | 1s | Première valeur de la propriété animation — 0,6 s pour un effet nerveux, 2 s pour une respiration lente. |
| Pas de délai par lettre (JS, ${.1*t}) | 0,1 | Multiplicateur du délai dans l’expression JS — 0,05 resserre la vague, 0,2 l’étire sur davantage de temps. |
| Texte source (JS, « "WAVE" ») | "WAVE" | Chaîne hardcodée dans e.innerHTML — remplacer par e.textContent pour utiliser le texte déjà présent dans le HTML. |
| Easing (.text-wave span, animation) | ease-in-out | Fonction de timing — linear pour un mouvement mécanique uniforme, cubic-bezier(0.4,0,0.2,1) pour un rebond naturel. |
| Variante amplitude réduite (classe CSS) | .text-wave | Substituer par .text-wave-v2 (keyframe waveV2, amplitude −10 px) pour un mouvement plus discret dans les contextes compacts. |
| Taille de fonte (.demo-text, font-size) | 2.5rem | Surcharger selon le contexte : 4–6 rem pour un hero, 0,85–1 rem pour un badge, 2,5–3 rem pour un titre éditorial. |
FAQ
<span> sans aria-hidden — le contenu textuel reste visible dans le DOM et Googlebot le lit comme du texte ordinaire. Aucune technique de masquage, aucun problème d’indexation.getElementById('waveText') — un seul élément. Pour plusieurs instances, remplacer par document.querySelectorAll('[data-wave]') et itérer : pour chaque élément, découper son textContent en <span> avec le délai progressif. La logique est identique, appliquée en boucle.<span> enfants sur lesquels la règle .text-wave span peut s’appliquer. Solution : inclure le JS (recommandé) ou découper manuellement le HTML en <span style="animation-delay: Xs"> par lettre.