Split Hover
Au survol, chaque lettre explose aléatoirement dans l'espace — un ressort CSS élastique la rappelle à sa position dès que la souris s'éloigne.
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
Au chargement, initSplitHover() découpe la chaîne caractère par caractère et enveloppe chaque lettre dans un <span data-index> rendu en inline-block. Ce préfixe rend chaque glyphe indépendamment transformable par le moteur CSS, sans toucher au flux de texte environnant.
Sur mouseenter, la classe .scattered s'ajoute au conteneur (ce qui abaisse l'opacity de chaque span à 0.3 via CSS) et chaque lettre reçoit un transform: translate(Xpx, Ypx) rotate(Rdeg) calculé avec Math.random() : amplitude X ±50 px, Y ±40 px, rotation ±45°. Les valeurs diffèrent à chaque survol — pas de trajectoire mémorisée.
Sur mouseleave, les transforms sont réinitialisés à translate(0,0) rotate(0deg) et la classe .scattered est retirée. La transition CSS cubic-bezier(.68, -.55, .265, 1.55) (courbe « back-out ») produit un dépassement bref au-delà de la position cible avant stabilisation — l'effet de ressort qui donne à l'animation son caractère élastique.
L'ensemble repose sur des transitions CSS et des événements DOM standard : aucun requestAnimationFrame, aucune librairie. Retirer les deux listeners mouseenter/mouseleave suffit à désactiver l'effet proprement, sans état résiduel.
Accessibilité
- prefers-reduced-motion ABSENT : le code ne détecte pas la préférence système. Les lettres s'animent systématiquement, même lorsque l'OS demande à réduire le mouvement. À implémenter manuellement en guarde autour des listeners si le contexte le requiert.
- Les
<span>de lettres ne portent aucun attribut ARIA. Un lecteur d'écran lit chaque lettre isolément (« H », « O », « V »…). Ajoutezaria-label="texte complet"sur le conteneur etaria-hidden="true"sur les spans enfants pour une restitution naturelle. - L'effet n'est déclenché que par
mouseenter/mouseleave— il est inactif au clavier et sur écran tactile. Aucun équivalentfocus/touchstartn'est prévu dans le code de référence. - Le contraste du texte au repos dépend entièrement du fond fourni par l'intégrateur. Prévoir un ratio ≥ 4,5:1 (WCAG AA) entre la couleur du texte et le fond.
- Le bouton
Resetprésent dans la démo ne porte pas dearia-label: l'étiquette visible « Reset » suffit en production, mais l'attributonclickinline est à remplacer par un listener pour respecter la séparation des responsabilités.
Compatibilité navigateur
Nécessite les transitions CSS et les événements DOM — supportés nativement dans tous les navigateurs modernes. Aucun Canvas, aucune API expérimentale.
Sur mobile et écran tactile, <code>mouseenter</code> ne se déclenche pas : les lettres restent dans leur position d'origine et le texte reste lisible. Aucune erreur JS, aucune mise en page cassée.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="demo-preview">
<!-- Le JS reconstruit ces spans via initSplitHover() -->
<span class="demo-text text-split-hover" id="splitHoverText">
<span data-index="0">H</span>
<span data-index="1">O</span>
<span data-index="2">V</span>
<span data-index="3">E</span>
<span data-index="4">R</span>
<span data-index="6">M</span>
<span data-index="7">E</span>
</span>
<!-- Bouton reset (démo) -->
<button class="replay-btn" onclick="replaySplitHover()">Reset</button>
</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 |
|---|---|---|
| Constante JS randomX (ligne ~14) | 100 | Amplitude de dispersion horizontale. Chaque lettre part jusqu'à ±(valeur/2) px. Augmenter pour un effet plus explosif, réduire pour un frémissement subtil. |
| Constante JS randomY (ligne ~15) | 80 | Amplitude de dispersion verticale (±(valeur/2) px). À égaliser avec randomX pour une dispersion isotrope, ou réduire pour un effet purement horizontal. |
| Constante JS randomRotate (ligne ~16) | 90 | Plage de rotation (±(valeur/2) degrés). Mettre à 0 pour supprimer la rotation et conserver uniquement la translation. |
| CSS transition-duration sur .text-split-hover span | .4s | Durée du retour élastique. Réduire à .2s pour une réponse nerveuse, augmenter à .7s pour une animation cinématique. |
| CSS cubic-bezier sur .text-split-hover span | (.68,-.55,.265,1.55) | Courbe d'élasticité du retour. Augmenter les valeurs négatives (ex. -.8) pour un ressort plus prononcé. Remplacer par ease-out pour supprimer le rebond. |
| CSS opacity sur .text-split-hover.scattered span | 0.3 | Opacité des lettres en état dispersé. 0 = disparition totale, 1 = pas d'atténuation (translation seule visible). |
| CSS font-size sur .demo-text | 2.5rem | Taille du texte — à adapter au contexte (1.5 rem pour une nav, 6 rem pour une headline pleine page). |
FAQ
initSplitHover() reconstruit les spans à partir d'une constante interne ('HOVER ME'). Modifiez cette chaîne dans le JS pour changer le texte affiché — la découpe en spans et les events sont régénérés automatiquement à l'appel..text-split-hover span { transition: transform .4s cubic-bezier(.68, -.55, .265, 1.55) }. Remplacez cubic-bezier(.68, -.55, .265, 1.55) par ease-out ou cubic-bezier(0,.8,.4,1) pour un retour fluide sans dépassement.mouseenter et mouseleave ne se déclenchent pas sur les appareils sans pointeur. Sur mobile, les lettres restent statiques — le texte reste lisible et aucune erreur n'est levée. Pour une version tactile, ajoutez des listeners touchstart/touchend qui appellent la même logique.