Text Shuffle Reveal
Chaque lettre parcourt une cascade de substitutions aléatoires avant de se verrouiller sur la bonne valeur — l'effet décodeur caractère par caractère, 100 % vanilla.
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 container .kt-text.kt-shuffle porte l'attribut data-text qui définit le texte cible. La fonction splitChars() lit cette valeur, vide l'élément et reconstruit autant de <span class="char" data-char="X">?</span> que de caractères : la valeur cible est archivée dans data-char, le textContent initial est un caractère aléatoire.
À chaque tick d'un setInterval (≈ 50 ms), chaque span reçoit un nouveau caractère tiré du pool CHARS (lettres A–Z + a–z, chiffres, symboles). Un compteur par position limite les substitutions à CYCLES_PER_CHAR itérations ; une fois la limite atteinte, l'intervalle est annulé et le span affiche la valeur data-char à pleine opacité blanche.
Un délai d'amorçage échelonné (STAGGER, ≈ 60 ms par position) décale les démarrages de gauche à droite via setTimeout : la première lettre se verrouille avant même que la dernière ait commencé à cycler, produisant la cascade révélatrice typique de l'effet.
Un listener click sur le container rappelle shuffleReveal() — chaque span retrouve une valeur aléatoire à demi-opacité et le cycle repart de zéro. La fonction splitChars() reconstruit la structure spans si le textContent a été modifié entre deux appels.
Accessibilité
- Pas de bloc
@media (prefers-reduced-motion: reduce)dans le code fourni — les utilisateurs ayant activé cette préférence OS voient l'animation cycler normalement. À ajouter : testermatchMedia('(prefers-reduced-motion: reduce)').matchesau démarrage et, si vrai, afficher directement la valeurdata-charsans lancer les intervalles. - Les
.charen transit ne portent pasaria-hidden— un lecteur d'écran peut lire les lettres aléatoires intermédiaires. Solution : ajouteraria-hidden="true"sur le container animé et fournir un élément<span class="sr-only">séparé contenant le texte cible. - Aucun attribut
roleniaria-labelsur le container par défaut — ajouteraria-label="texte cible"etaria-live="off"si le container est le seul véhicule du contenu textuel. - Le déclencheur
clickn'est pas accessible au clavier (pas detabindexni listenerkeydown) — ajoutertabindex="0"et écouterEnter/Spacepour les utilisateurs clavier. - Les caractères transitoires sont affichés en
rgba(255,255,255,0.5)sur fond#0a0a0f(ratio ≈ 3,5:1, sous le seuil WCAG AA de 4,5:1). Acceptable pour une animation brève sur fond sombre ; à renforcer si la durée de cycle est longue ou le fond plus clair.
Compatibilité navigateur
Nécessite DOM Level 2, setInterval et addEventListener — présents dans tous les navigateurs modernes depuis 2012.
Si JS est désactivé, les spans <code>.char</code> affichent les caractères aléatoires pré-générés — le contenu n'est pas lisible. Prévoir un <code><noscript></code> ou un attribut <code>aria-label</code> sur le container pour rendre le texte accessible.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="kt-text kt-shuffle" id="shuffle1" data-text="VOTRE TEXTE" style="cursor: pointer;">
<!-- splitChars() génère dynamiquement les spans :
<span class="char" data-char="V">?</span>
<span class="char" data-char="O">?</span>
… un span par caractère de data-text -->
</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 |
|---|---|---|
| data-text | "SHUFFLE" | Texte à révéler. Modifiable à la volée : mettre à jour l'attribut, rappeler splitChars(el) puis shuffleReveal(el). |
| CHARS (const JS) | A-Za-z0-9 + symboles | Pool de caractères aléatoires. Réduire à 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' pour un rendu typographique pur ; étendre aux chiffres et symboles pour l'esthétique hacker. |
| CYCLE_SPEED (const JS) | 50 ms | Intervalle en ms entre chaque substitution par position. 35 ms = très rapide (hacker), 80–100 ms = lent et éditorial. |
| CYCLES_PER_CHAR (const JS) | 8 | Nombre de substitutions aléatoires avant verrouillage. Augmenter (12–16) pour prolonger la tension ; réduire (4–5) pour une révélation quasi-immédiate. |
| STAGGER (const JS) | 60 ms | Décalage en ms entre le démarrage de chaque position. 0 = toutes les lettres cyclent en même temps ; 120 ms = cascade très progressive. |
| .kt-text { font-size } | 2.2rem | Taille du texte — la hauteur de ligne et le letter-spacing héritent automatiquement. |
| couleur transitoire (inline) | rgba(255,255,255,0.5) | Couleur des chars aléatoires en transit. La valeur verrouillée bascule vers #fff (pleine opacité) à l'issue du cycle. |
FAQ
data-text du container, appelez splitChars(el) pour reconstruire les spans, puis relancez l'animation : el.setAttribute('data-text','NOUVEAU'); splitChars(el); shuffleReveal(el);click par un IntersectionObserver sur le container. Dans le callback, appelez shuffleReveal(el) quand entry.isIntersecting est vrai, puis observer.disconnect() si vous ne souhaitez qu'un seul déclenchement.shuffleReveal dans un useEffect après le montage ; dans Vue, dans le hook mounted ; dans Svelte, dans onMount. L'animation ne touche que le textContent et le style.color des spans — pas de conflits avec le rendu du framework.