Magnetic Cursor Text
Chaque caractère devient un aimant : il suit le curseur dans un rayon configurable et revient en place avec une transition élastique CSS.
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
La fonction splitChars(el) lit l'attribut data-text de l'élément cible et remplace son contenu texte par une série de <span class="char"> — un par glyphe. Les espaces sont convertis en espace insécable pour ne pas s'effondrer dans le flux en ligne. Chaque span est display: inline-block, ce qui rend chaque lettre déplaçable indépendamment sans affecter le reflow du reste du texte.
La règle CSS .kt-magnetic .char { transition: transform .3s cubic-bezier(.25, .46, .45, .94) } confie entièrement l'animation au navigateur. La courbe choisie produit un léger dépassement sur le retour — le « rebond élastique » caractéristique de l'effet magnétique — sans aucune boucle requestAnimationFrame côté JS. Le script écrit uniquement le style final ; le navigateur interpole le mouvement.
Sur chaque événement mousemove, la distance euclidienne entre le curseur et le centre de la bounding box de chaque .char est calculée. Si elle est inférieure au rayon magnétique (constante JS, ~120 px par défaut), la lettre reçoit style.transform = translate(dx·f, dy·f) où f = (1 − dist/radius) × strength — un facteur qui décroît linéairement à zéro en bordure de champ, simulant la dégression du flux magnétique.
Quand le curseur quitte le rayon ou le conteneur, les transforms sont réinitialisés à la chaîne vide. La transition CSS ramène chaque caractère à sa position naturelle — aucun état à nettoyer côté JS. L'attribut data-text stocke la chaîne d'origine et permet à splitChars() de reconstruire les spans si le contenu est modifié dynamiquement.
Accessibilité
- prefers-reduced-motion absent : le code livré ne désactive pas la transition. À ajouter en production :
@media (prefers-reduced-motion: reduce) { .kt-magnetic .char { transition: none } }pour supprimer le déplacement des lettres chez les utilisateurs sensibles au mouvement. - Les
<span class="char">peuvent être lus lettre par lettre par certains lecteurs d'écran. Enveloppez le.kt-textdans un élément portantaria-label="VOTRE TEXTE"et ajoutezaria-hidden="true"sur chaque.charpour que le mot soit annoncé en un seul bloc. - Contraste : la couleur par défaut
#fffsur fond#0a0a0fatteint un ratio ~20:1 (WCAG AAA). À vérifier après tout changement de palette. - L'effet est déclenché par
mousemoveuniquement — aucune alternative clavier ou tactile. Pour un titre purement décoratif, ce n'est pas un blocage d'accessibilité ; le texte reste lisible et positionné correctement sans interaction. - Pas de
roleni d'aria-labelsur le conteneur dans le code livré : le texte étant du HTML sémantique, aucun rôle supplémentaire n'est requis si la hiérarchie des titres est respectée.
Compatibilité navigateur
Utilise uniquement CSS transform + transition et l'événement mousemove — aucune dépendance canvas, WebGL ou requestAnimationFrame.
Sans événements souris (tactile, navigateur ancien), les caractères restent à leur position naturelle. Le texte est parfaitement lisible et le layout ne casse pas.
Le code
Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :
<div class="demo-preview">
<div class="kt-text kt-magnetic" id="magnetic1" data-text="VOTRE TEXTE">
<!-- Généré par splitChars() ou écrit manuellement -->
<span class="char" data-char="V">V</span>
<span class="char" data-char="O">O</span>
<span class="char" data-char="T">T</span>
<span class="char" data-char="R">R</span>
<span class="char" data-char="E">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 |
|---|---|---|
| font-size sur .kt-text | 2.2rem | Taille des caractères. 4–6 rem pour un hero, 1.4–2 rem pour une navigation. |
| font-weight sur .kt-text | 800 | Graisse de la police. 900 pour un impact maximal, 400–600 pour un style éditorial plus doux. |
| color sur .kt-text | #fff | Couleur des caractères. Accepte toute valeur CSS : hex, oklch, voire un dégradé via background-clip: text. |
| letter-spacing sur .kt-text | .02em | Espacement entre lettres. Élargissez à 0,06–0,12 em sur les grandes fontes pour un effet monumental. |
| transition-duration sur .kt-magnetic .char | 0.3s | Durée du retour élastique. 0,15 s = réponse vive et sèche, 0,5 s = magnétisme lent et organique. |
| transition-timing-function sur .kt-magnetic .char | cubic-bezier(.25,.46,.45,.94) | Courbe de retour. Essayez cubic-bezier(.34,1.56,.64,1) pour un rebond plus prononcé. |
| data-text sur .kt-text | MAGNETIC | Texte source utilisé par splitChars() pour générer les spans. Modifiez sans toucher au HTML. |
| Rayon magnétique (constante JS) | 120 | Distance en pixels sous laquelle un caractère est attiré. Augmentez pour un champ plus large. |
| Force d'attraction (constante JS) | 0.38 | Facteur de déplacement maximal. 0 = aucun mouvement, 0,6 = déplacement très prononcé. |
FAQ
splitChars() traite chaque caractère, espaces inclus. Pour des phrases multi-mots, mieux vaut un .kt-text.kt-magnetic par mot — les transforms peuvent sinon créer des chevauchements visuels si le déplacement dépasse l'espace naturel du mot.e.clientX / e.clientY au calcul de distance de chaque .char. Le champ magnétique s'active alors dès que le curseur entre dans la zone parente, bien avant de survoler les lettres.transform: translate() est appliqué par le compositor thread du navigateur — aucun reflow de layout, aucun repaint de couche. Les transitions CSS sont traitées indépendamment du thread JS, garantissant 60 fps même avec un document chargé.