Wave Text
Animation CSS pure : chaque lettre rebondit verticalement avec un délai décalé de 0,08 s — une vague continue sans une ligne de JavaScript.
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 ktWave : de translateY(0) à translateY(-18px) puis retour, en 2 s avec un timing ease-in-out infini. Chaque <span class="char"> porte la propriété CSS personnalisée --delay — 0 s pour le premier caractère, +0,08 s par caractère suivant — assignée à animation-delay via la règle .kt-wave .char { animation-delay: var(--delay) }. C'est ce décalage qui produit la propagation gauche-droite de la vague.
Chaque .char est en display: inline-block — indispensable car translateY est sans effet sur les éléments inline. La propriété user-select: none sur .kt-text empêche la sélection accidentelle du texte animé. Aucun canvas ni JS de rendu n'est impliqué : le navigateur gère l'animation entièrement en couche de composition.
La décomposition du texte en spans est soit pré-générée dans le HTML (méthode statique utilisée dans le code fourni), soit produite dynamiquement par la fonction splitChars(el) qui lit data-text ou le textContent de l'élément. Attention : splitChars ne pose pas les --delay — ils doivent être ajoutés via CSS ou par un script complémentaire après l'appel.
Le CSS embarque plusieurs variantes prêtes à l'emploi au-delà de .kt-wave : .kt-elastic (entrée unique par écrasement élastique), .kt-scatter / .kt-whirlpool (assemblage depuis positions dispersées), .kt-magnetic (répulsion curseur), .kt-liquid (déformation au survol lettre par lettre) et .kt-explosion (clic). La variante active est sélectionnée par la deuxième classe sur .kt-text — aucune modification de keyframe nécessaire.
Accessibilité
- prefers-reduced-motion absent : le code ne contient aucune règle
@media (prefers-reduced-motion: reduce)— l'animation infinie tourne même si l'OS signale cette préférence. Recommandation : ajoutez@media (prefers-reduced-motion: reduce) { .kt-wave .char { animation: none; } }. - Les
.charindividuels ne portent pasaria-hidden— les lecteurs d'écran épellent chaque lettre séparément. Recommandation : ajoutezrole="img" aria-label="[texte complet]"sur le conteneur.kt-textetaria-hidden="true"sur chaque.char. - Le texte blanc (#fff) sur fond sombre (#0a0a0f) dépasse un ratio de contraste de 18:1 — conforme WCAG AA et AAA.
user-select: noneest posé sur.kt-text: le texte ne peut pas être sélectionné ni copié. Acceptable pour du texte décoratif ; à supprimer si le texte transporte une information utile.- L'animation
.kt-wavene requiert aucune interaction clavier ou souris — aucun piège au focus n'est introduit, la navigation au clavier passe librement à travers le composant.
Compatibilité navigateur
Repose sur les animations CSS et les propriétés CSS personnalisées (var(--delay)) — fonctionnalités stables dans tous les navigateurs modernes depuis 2017.
Si les propriétés CSS personnalisées ne sont pas supportées, tous les caractères s'animent en synchrone (rebond simultané). Le texte reste lisible et aucune erreur JS n'est levée.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="demo-preview">
<div class="kt-text kt-wave" id="wave1" data-text="WAVE EFFECT"
role="img" aria-label="Wave Effect">
<!-- Une <span class="char"> par caractère, --delay incrémenté de 0,08 s -->
<span class="char" data-char="W" style="--delay: 0s;" aria-hidden="true">W</span>
<span class="char" data-char="A" style="--delay: 0.08s;" aria-hidden="true">A</span>
<span class="char" data-char="V" style="--delay: 0.16s;" aria-hidden="true">V</span>
<span class="char" data-char="E" style="--delay: 0.24s;" aria-hidden="true">E</span>
<!-- … -->
</div>
</div>
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 |
|---|---|---|
| animation-duration (.kt-wave .char) | 2s | Durée d'un cycle de vague. Réduisez à 1,2 s pour une vague vive ; montez à 3 s pour un mouvement lent et fluide. |
| translateY dans @keyframes ktWave (50 %) | -18px | Amplitude verticale du rebond. Augmentez à -30 px pour une vague prononcée, réduisez à -8 px pour un effet subtil. |
| --delay (par .char) | 0,08 s par lettre | Décalage de timing entre chaque lettre. Un écart plus grand (0,15 s) étire la vague ; un écart plus petit (0,04 s) la resserre. |
| animation-timing-function (.kt-wave .char) | ease-in-out | Courbe du mouvement. cubic-bezier(.45, 0, .55, 1) donne une vague plus élastique ; linear produit un roulement mécanique régulier. |
| font-size (.kt-text) | 2,2rem | Taille du texte. Passez à 4–5 rem pour un hero, 1,6 rem pour un badge ou label. |
| color (.kt-text) | #fff | Couleur des lettres. Combinez background: linear-gradient(…) + -webkit-background-clip: text + color: transparent pour un texte dégradé. |
| letter-spacing (.kt-text) | 0,02em | Espacement inter-lettres. Augmentez à 0,15 em pour un rendu type affiche ; réduisez à -0,02 em pour un texte compact. |
| Variante (.kt-text) | .kt-wave | Remplacez .kt-wave par .kt-elastic, .kt-liquid ou .kt-explosion pour changer d'animation sans toucher aux keyframes. |
FAQ
.kt-wave est 100 % CSS. Si le HTML est pré-généré avec les <span class="char"> et les valeurs --delay en ligne, zéro JS n'est requis. La fonction splitChars() est un utilitaire optionnel pour générer ces spans dynamiquement ; elle ne pose pas les délais (à compléter via CSS ou un script complémentaire).translateY dans @keyframes ktWave à 50 % — actuellement -18px. Augmentez la valeur absolue pour une vague plus haute, réduisez-la pour un effet discret. Vous pouvez aussi rendre l'amplitude variable par lettre en substituant une propriété CSS personnalisée --amp à la valeur fixe dans le keyframe.visibilitychange ni IntersectionObserver n'est nécessaire pour économiser le CPU.