Texte✨ Premium

Text Whirlpool

Les caractères s'envolent en orbite circulaire puis convergent vers le texte lisible d'un seul mouvement élastique — 100 % transitions CSS, zéro canvas.

JSAnimationOrbit

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

Portfolio créatif — Titre principal animé à l'entrée de page — Text Whirlpool exemple 1

① Portfolio créatif — Titre principal animé à l'entrée de page

QuandLa page se charge ou le visiteur atteint le premier écran — un grand mot-clé (STUDIO, MOTION, VISUAL…) surgit de son orbite et se pose, captant immédiatement l'attention.
PourquoiSur une large surface vierge, la convergence circulaire crée un effet typographique fort sans surcharger visuellement ; le texte est parfaitement lisible dès que les chars se stabilisent.
Réglagesfont-size 5–7rem, rayon orbital ≈ 120 px (ajuster RADIUS dans l'init), déclenchement automatique via IntersectionObserver, palette monochrome blanc sur fond sombre.
Page produit premium — Nom révélé à l'ouverture de fiche — Text Whirlpool exemple 2

② Page produit premium — Nom révélé à l'ouverture de fiche

QuandLe visiteur ouvre la fiche d'un produit haut de gamme — le nom tourbillonne depuis l'orbite et se pose en un seul mouvement, comme un dévoilement solennel unique à cette visite.
PourquoiUn seul événement par page, jamais répété : la convergence circulaire confère au nom une gravité que ni un fondu ni un glissement ne peuvent offrir. L'animation spectaculaire reste exceptionnelle car elle n'est pas consommée en boucle.
Réglagesfont-size 3–4rem, rayon orbital ≈ 90 px (RADIUS 90 dans l'init JS), transition 1.2s cubic-bezier(.34,1.56,.64,1), opacité orbitale 0.424, palette dorée ou blanc platine sur fond quasi-noir — déclenchement automatique à l'ouverture de page, pas de replay au clic.
Jeu web — Révélation du titre ou du niveau — Text Whirlpool exemple 3

③ Jeu web — Révélation du titre ou du niveau

QuandL'écran de titre d'un mini-jeu s'affiche ou un nouveau niveau est annoncé — les lettres tourbillonnent avant de se figer sur le nom du niveau ou du jeu.
PourquoiL'orbite circulaire et l'effet ressort sont cinématiques et correspondent aux codes visuels des jeux ; le replay au clic permet de ré-animer le titre à chaque révélation de niveau sans recharger la page.
Réglagesfont-size 3rem gras, couleurs vives (doré ou néon), rayon ≈ 90 px, repeat on click pour chaque annonce de niveau.

Comment ça marche

La fonction utilitaire splitChars() décompose l'attribut data-text en autant de <span class="char"> que de caractères. L'init JS calcule ensuite pour chaque span une position angulaire sur un cercle de rayon ≈ 77 px selon la formule angle = phase + index × (2π / n) (n = nombre de caractères, phase ≈ 14,4°), convertie en coordonnées cartésiennes via Math.cos / Math.sin.

Chaque char reçoit un style inline position:absolute; transform:translate(x,y) rotate(14.4deg); opacity:0.424; transition:none. Le transition:none inline est crucial : il bloque toute animation au chargement, même si la règle CSS .kt-whirlpool .char { transition:1.2s cubic-bezier(.34,1.56,.64,1) } est déjà en place. Le parent .kt-whirlpool est rendu position:relative par le JS, ce qui le positionne à zéro volume dans son conteneur flex-centré — les chars orbitent donc autour du centre visuel de la zone.

Pour lancer l'animation, deux requestAnimationFrame imbriqués suppriment l'override transition:none (via c.style.removeProperty('transition')) puis ajoutent la classe .active au conteneur. Les règles .kt-whirlpool.active .char { position:relative!important; transform:translate(0,0) rotate(0deg)!important; opacity:1!important } s'appliquent alors : chaque char quitte son orbite et rejoint son emplacement naturel dans le flux de texte. Le cubic-bezier(.34,1.56,.64,1) produit un léger dépassement puis rebond — effet ressort (spring).

Un clic sur le conteneur relance le cycle : retrait de .active, réapplication des styles inline circulaires avec transition:none, puis re-déclenchement via double-rAF. L'effet est entièrement DOM — aucun canvas, aucune librairie externe.

Accessibilité

  • prefers-reduced-motion : non implémenté dans le code fourni. Solution minimale à ajouter : @media (prefers-reduced-motion: reduce) { .kt-whirlpool .char { transition: none !important; } } et déclencher directement .active sans attendre le double-rAF.
  • Aucun attribut aria-* dans la structure HTML de base — ajouter role="img" et aria-label="[votre texte]" sur le conteneur si l'effet tient lieu de titre décoratif.
  • Le texte est dans le DOM sous forme de <span> lisibles : les lecteurs d'écran accèdent au contenu textuel indépendamment de l'animation.
  • L'interaction clavier n'est pas nativement supportée (conteneur <div> non focusable) — ajouter tabindex="0" et un listener keydown (Entrée/Espace) pour rendre le replay accessible.
  • Aucun aria-live : le changement d'état visuel n'est pas annoncé aux technologies d'assistance.

Compatibilité navigateur

Nécessite les transitions CSS et requestAnimationFrame — supportés dans tous les navigateurs modernes. Zéro dépendance externe.

Chrome 90+✓ Complet
Firefox 90+✓ Complet
Safari 15+✓ Complet
Edge 90+✓ Complet
Mobile iOS✓ Touch OK
Android Chrome✓ Complet

Sans transitions CSS, les caractères passent directement à leur état lisible final sans animation — aucune erreur JS, le texte reste affiché et lisible.

Le code

Structure HTML à coller dans votre page (CSS + JS disponibles avec un compte premium) :

index.html — structure
<div class="demo-preview">
  <div class="kt-text kt-whirlpool" id="whirlpool1" data-text="VORTEX" style="cursor: pointer;">
    <!-- Un <span class="char" data-char="V">V</span> par caractère
         positionné en orbite par l'init JS (position:absolute + translate) -->
  </div>
  <span class="demo-hint">Cliquer pour relancer</span>
</div>
🔒 Débloquer le code complet — à partir de 2,99 € le 1er mois

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éfautEffet
data-text "VORTEX" Texte à animer — modifiez directement l'attribut HTML. Le nombre de caractères ajuste automatiquement l'espacement angulaire (360° / n).
font-size sur .kt-text 2.2rem Taille des caractères. Une taille plus grande appelle un rayon orbital plus large — augmentez la constante RADIUS dans le JS d'initialisation en proportion.
color sur .kt-text #fff Couleur des caractères en état lisible. L'opacité en orbite (0.424) est imposée par le style inline du JS init et s'applique quelle que soit la couleur.
transition dans .kt-whirlpool .char 1.2s cubic-bezier(.34, 1.56, .64, 1) Durée et courbe de la convergence. Augmentez à 1.8s pour un mouvement lent et cinematique, réduisez à 0.6s pour une animation vive. Modifiez le cubic-bezier pour plus ou moins de rebond (2e valeur > 1 = dépassement).
RADIUS (constante JS init) ~77 Rayon du cercle orbital en pixels. Calibrez selon le nombre de caractères et la font-size — un mot de 4 lettres en 5rem appelle un rayon de 100–120 px.
opacity: 0.424 (style inline JS init) 0.424 Opacité des caractères pendant l'orbite, avant convergence. 0 = invisible au départ (surgissement soudain), 0.7 = semi-visible (effet plus doux).
rotate(14.4deg) (style inline JS init) 14.4deg Rotation uniforme appliquée à tous les caractères en orbite. 0deg = lettres droites pendant l'orbite, 45deg = caractères fortement inclinés.

FAQ

Oui — l'effet est 100 % vanilla : des <span> DOM, des transitions CSS et quelques lignes de JS pour le calcul des positions orbitales. Zéro dépendance npm, zéro canvas. Compatible avec tout framework : enveloppez le conteneur dans un composant, déclenchez l'ajout de .active depuis votre logique et retirez-le pour réinitialiser.
Modifiez l'attribut data-text directement dans le HTML (data-text="STUDIO"). Le JS init lit cet attribut, recrée les <span class="char"> et recalcule les positions angulaires automatiquement — aucune modification du script n'est nécessaire.
Oui — l'init JS doit cibler chaque .kt-whirlpool par élément (et non par variable globale) : donnez un id distinct à chaque conteneur. Chacun dispose alors de son propre état .active, de son listener clic isolé et de ses chars indépendants. Aucune variable d'état n'est partagée entre instances.