Blog / CSS/JS

Animer le texte lettre par lettre avec JavaScript

Maitrisez les techniques de text splitting pour creer des animations de texte spectaculaires : reveal letter-by-letter, effet scramble, typewriter avance et bien plus encore.

Introduction au Text Splitting

Le text splitting est une technique fondamentale pour creer des animations de texte avancees. Le principe est simple : decomposer un texte en elements individuels (lettres, mots, ou lignes) pour pouvoir les animer independamment.

Cette technique est utilisee par les plus grands sites web et agences creatives pour creer des experiences memorables. Des titres qui se revelent lettre par lettre aux effets de glitch spectaculaires, les possibilites sont infinies.

💡
Pourquoi utiliser le text splitting ?

Animer un texte entier ne permet que des transformations globales (fade, slide). En splitant le texte, chaque caractere devient un element animable individuellement, ouvrant la porte a des effets bien plus riches.

Dans ce guide complet, nous allons explorer 6 techniques differentes de text splitting et d'animation, du plus simple au plus elabore. Chaque exemple inclut le code complet, pret a copier.

Split par lettres avec JavaScript

La premiere etape consiste a creer une fonction qui va decomposer notre texte en caracteres individuels. Chaque lettre sera enveloppee dans un <span> pour pouvoir etre animee.

split-by-chars.js
function splitByChars(element) {
  // Sauvegarde du texte original
  const text = element.textContent;

  // Vide l'element
  element.innerHTML = '';

  // Split chaque caractere
  text.split('').forEach((char, index) => {
    const span = document.createElement('span');
    span.className = 'char';

    // Gestion des espaces (utilise un espace insecable)
    span.textContent = char === ' ' ? '\u00A0' : char;

    // Delay progressif pour l'animation
    span.style.animationDelay = `${index * 0.05}s`;

    element.appendChild(span);
  });

  return element;
}

// Utilisation
const title = document.querySelector('.my-title');
splitByChars(title);

Points cles de l'implementation

  • Espaces insecables : Les espaces normaux seraient ignores par le navigateur. On utilise \u00A0 pour les preserver.
  • Animation delay : Chaque caractere recoit un delai progressif (0.05s par defaut) pour creer l'effet de cascade.
  • Classe .char : Permet de cibler tous les caracteres en CSS pour l'animation.

Split par mots

Parfois, animer mot par mot est plus adapte, notamment pour les phrases longues ou les titres. Le principe est similaire, mais on split sur les espaces.

Bienvenue sur Effects Lab
split-by-words.js
function splitByWords(element) {
  const text = element.textContent;
  const words = text.split(' ');

  element.innerHTML = '';

  words.forEach((word, index) => {
    const span = document.createElement('span');
    span.className = 'word';
    span.textContent = word;
    span.style.animationDelay = `${index * 0.15}s`;

    element.appendChild(span);
  });
}

// CSS associe
/*
.word {
  display: inline-block;
  margin: 0 8px;
  opacity: 0;
  transform: translateY(20px) rotateX(-90deg);
}

.animate .word {
  animation: wordReveal 0.6s forwards;
}

@keyframes wordReveal {
  to {
    opacity: 1;
    transform: translateY(0) rotateX(0);
  }
}
*/

Animations letter-by-letter

Une fois le texte splite, on peut appliquer differents types d'animations. Voici les 4 animations les plus populaires avec leurs demonstrations interactives.

Fade In Stagger

L'animation la plus classique : chaque lettre apparait progressivement avec un fondu.

EFFECTS LAB

Slide Up

Les lettres apparaissent en montant depuis le bas, creant un effet de revelation dynamique.

SLIDE UP

Wave Effect

Une animation en boucle ou les lettres ondulent comme une vague. Parfait pour attirer l'attention.

WAVE

Scale Pop

Chaque lettre apparait avec un effet de zoom, comme si elle "popait" a l'ecran.

POP!
animations.css
/* Base : chaque caractere est invisible par defaut */
.split-text .char {
  display: inline-block;
  opacity: 0;
}

/* 1. Fade In */
.split-text.animate-fade .char {
  animation: charFadeIn 0.5s forwards;
}

@keyframes charFadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* 2. Slide Up */
.split-text.animate-slide .char {
  animation: charSlideUp 0.5s forwards;
}

@keyframes charSlideUp {
  from {
    opacity: 0;
    transform: translateY(30px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 3. Wave (animation continue) */
.split-text.animate-wave .char {
  opacity: 1;
  animation: charWave 1.5s ease-in-out infinite;
}

@keyframes charWave {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-15px); }
}

/* 4. Scale Pop */
.split-text.animate-scale .char {
  animation: charScale 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

@keyframes charScale {
  from {
    opacity: 0;
    transform: scale(0);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

Effet Scramble / Shuffle

L'effet scramble (ou shuffle) est l'un des plus impressionnants : le texte affiche des caracteres aleatoires qui se stabilisent progressivement pour reveler le texte final. C'est l'effet "hacker" par excellence.

DECRYPTING...
scramble-effect.js
class ScrambleText {
  constructor(element, options = {}) {
    this.element = element;
    this.chars = options.chars || '!@#$%^&*()_+-=[]{}|;:,.<>?';
    this.duration = options.duration || 2000;
    this.originalText = element.textContent;
  }

  scramble(newText) {
    const target = newText || this.originalText;
    const length = target.length;
    const startTime = Date.now();

    const animate = () => {
      const elapsed = Date.now() - startTime;
      const progress = Math.min(elapsed / this.duration, 1);

      // Nombre de caracteres reveles
      const revealed = Math.floor(progress * length);

      let result = '';
      for (let i = 0; i < length; i++) {
        if (i < revealed) {
          // Caractere final
          result += target[i];
        } else if (target[i] === ' ') {
          // Preserve les espaces
          result += ' ';
        } else {
          // Caractere aleatoire
          result += this.chars[Math.floor(
            Math.random() * this.chars.length
          )];
        }
      }

      this.element.textContent = result;

      if (progress < 1) {
        requestAnimationFrame(animate);
      }
    };

    animate();
  }
}

// Utilisation
const scrambler = new ScrambleText(
  document.querySelector('.scramble-text'),
  { duration: 2000 }
);
scrambler.scramble('ACCESS GRANTED');
⚠️
Performance

L'effet scramble met a jour le DOM a chaque frame. Pour de longues chaines de caracteres, envisagez de limiter le framerate ou d'utiliser textContent plutot que innerHTML pour de meilleures performances.

Effet Typewriter avance

L'effet machine a ecrire est un classique indemodable. Voici une implementation avancee avec curseur clignotant, support de la suppression, et possibilite d'enchainer plusieurs textes.

typewriter.js
class Typewriter {
  constructor(element, options = {}) {
    this.element = element;
    this.typeSpeed = options.typeSpeed || 100;
    this.deleteSpeed = options.deleteSpeed || 50;
    this.pauseTime = options.pauseTime || 2000;
    this.texts = options.texts || [];
    this.loop = options.loop !== undefined ? options.loop : true;
    this.currentIndex = 0;
    this.isRunning = false;
  }

  async type(text) {
    for (let i = 0; i <= text.length; i++) {
      this.element.textContent = text.slice(0, i);
      await this.sleep(this.typeSpeed);
    }
  }

  async delete(text) {
    for (let i = text.length; i >= 0; i--) {
      this.element.textContent = text.slice(0, i);
      await this.sleep(this.deleteSpeed);
    }
  }

  sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  async start() {
    this.isRunning = true;

    while (this.isRunning) {
      const text = this.texts[this.currentIndex];

      await this.type(text);
      await this.sleep(this.pauseTime);
      await this.delete(text);
      await this.sleep(500);

      this.currentIndex = (this.currentIndex + 1) % this.texts.length;

      if (!this.loop && this.currentIndex === 0) break;
    }
  }

  stop() {
    this.isRunning = false;
  }
}

// Utilisation
const typewriter = new Typewriter(
  document.querySelector('.typewriter-text'),
  {
    texts: ['Developer', 'Designer', 'Creator'],
    typeSpeed: 80,
    deleteSpeed: 40,
    pauseTime: 1500
  }
);
typewriter.start();

Librairies recommandees

Si vous ne souhaitez pas coder vous-meme ces effets, plusieurs excellentes librairies peuvent vous faire gagner du temps.

Librairie Taille Split Animations Note
SplitType ~5KB Via CSS/GSAP Le plus populaire
GSAP SplitText ~10KB Premium, le plus puissant
Splitting.js ~2KB Via CSS Ultra-leger
Typed.js ~5KB Typewriter only Specialise typewriter

Exemple avec SplitType

splittype-example.js
// Installation: npm install split-type
import SplitType from 'split-type';

// Split le texte en caracteres
const text = new SplitType('.my-title', {
  types: 'chars, words',
  tagName: 'span'
});

// Acces aux elements
console.log(text.chars);  // Array des  caracteres
console.log(text.words);  // Array des  mots

// Avec GSAP pour l'animation
gsap.from(text.chars, {
  opacity: 0,
  y: 20,
  stagger: 0.05,
  duration: 0.5,
  ease: 'power2.out'
});
📚
Ressources utiles

Consultez la documentation SplitType pour plus d'options avancees comme le split par lignes ou la preservation des styles.

Bonnes pratiques

Avant de deployer vos animations de texte en production, gardez ces conseils en tete.

Performance

  • Utilisez transform et opacity pour les animations - ces proprietes sont optimisees par le GPU
  • Evitez d'animer trop d'elements simultanement - plus de 50 caracteres peut ralentir les appareils mobiles
  • Preferez will-change avec parcimonie sur les elements animes

Accessibilite

  • Respectez prefers-reduced-motion pour les utilisateurs sensibles aux mouvements
  • Ne bloquez pas la lecture - le texte final doit etre visible rapidement
  • Conservez le texte accessible aux lecteurs d'ecran
accessibility.css
/* Desactive les animations si l'utilisateur le souhaite */
@media (prefers-reduced-motion: reduce) {
  .split-text .char,
  .word-split .word {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

SEO

  • Le texte doit etre present dans le HTML initial, pas genere uniquement par JS
  • Evitez de remplacer le texte par des images ou canvas
  • Les spans n'affectent pas le SEO tant que le contenu textuel est preserved

Conclusion

Le text splitting est une technique puissante qui ouvre la porte a des animations de texte spectaculaires. Que vous choisissiez d'implementer votre propre solution ou d'utiliser une librairie, les possibilites sont infinies.

Nous avons couvert les techniques essentielles :

  • Split par caracteres pour les animations letter-by-letter
  • Split par mots pour les revelations plus fluides
  • Animations CSS : fade, slide, wave, scale
  • Effet scramble pour un look "hacker"
  • Typewriter pour l'effet machine a ecrire

N'hesitez pas a combiner ces techniques et a experimenter. Les meilleures animations sont souvent celles qui surprennent tout en restant subtiles.

🚀
Allez plus loin

Decouvrez notre bibliotheque d'effets pour des animations de texte pretes a l'emploi, avec code copiable en un clic.