ITSkillsCenter
Développement Web

Tutoriel : Créer un effet de machine à écrire en JavaScript

5 min de lecture

Ce que vous allez créer

L’effet de machine à écrire (typewriter effect) affiche un texte caractère par caractère, comme si quelqu’un le tapait en direct. C’est un effet visuel populaire pour les pages d’accueil, les portfolios et les landing pages. Dans ce tutoriel, vous allez construire 3 versions progressives : une basique, une avec suppression et réécriture, et une version réutilisable avec des options configurables.

Version 1 : l’effet typewriter basique

Le principe est simple : on prend une chaîne de caractères, on la découpe, et on ajoute un caractère à la fois dans un élément HTML avec un setTimeout ou setInterval.

Le HTML

<div class="typewriter-container">
  <h1 id="typewriter"></h1>
  <span class="cursor">|</span>
</div>

Le CSS pour le curseur clignotant

.typewriter-container {
  font-family: 'Courier New', monospace;
  font-size: 2rem;
  display: flex;
  align-items: center;
}

.cursor {
  animation: blink 0.7s infinite;
  font-weight: 100;
  margin-left: 2px;
}

@keyframes blink {
  0%, 50% { opacity: 1; }
  51%, 100% { opacity: 0; }
}

Le JavaScript

function typeWriter(element, text, speed = 80) {
  let index = 0;
  
  function taper() {
    if (index < text.length) {
      element.textContent += text.charAt(index);
      index++;
      setTimeout(taper, speed);
    }
  }
  
  taper();
}

// Lancer l'effet
const el = document.getElementById('typewriter');
typeWriter(el, 'Bienvenue sur ITSkillsCenter', 80);

Comment ça fonctionne : la fonction taper() s’appelle elle-même via setTimeout à chaque itération. À chaque appel, elle ajoute un caractère au contenu de l’élément et incrémente l’index. Quand l’index atteint la longueur du texte, elle s’arrête.

Version 2 : écrire, effacer et réécrire (effet boucle)

Cette version affiche un mot, l’efface, puis affiche le suivant. Parfait pour afficher plusieurs compétences ou services sur une page d’accueil.

function typewriterLoop(element, words, typeSpeed = 100, eraseSpeed = 50, pauseTime = 2000) {
  let wordIndex = 0;
  let charIndex = 0;
  let isErasing = false;

  function animate() {
    const currentWord = words[wordIndex];
    
    if (!isErasing) {
      // Mode écriture
      element.textContent = currentWord.substring(0, charIndex + 1);
      charIndex++;
      
      if (charIndex === currentWord.length) {
        // Mot complet → pause puis effacer
        isErasing = true;
        setTimeout(animate, pauseTime);
        return;
      }
      setTimeout(animate, typeSpeed);
    } else {
      // Mode suppression
      element.textContent = currentWord.substring(0, charIndex - 1);
      charIndex--;
      
      if (charIndex === 0) {
        // Mot effacé → passer au suivant
        isErasing = false;
        wordIndex = (wordIndex + 1) % words.length;
        setTimeout(animate, 500);
        return;
      }
      setTimeout(animate, eraseSpeed);
    }
  }

  animate();
}

// Utilisation
const el = document.getElementById('typewriter');
typewriterLoop(el, [
  'Développeur Web',
  'Designer UI/UX', 
  'Freelance à Dakar',
  'Passionné de code'
]);

Points clés :

  • wordIndex cycle entre les mots grâce à l’opérateur modulo %
  • L’effacement est plus rapide que l’écriture (50ms vs 100ms) pour un rendu naturel
  • Une pause de 2 secondes après chaque mot complet laisse le temps de lire

Version 3 : composant réutilisable avec Promesses

Cette version utilise les Promesses et async/await pour un code plus propre et plus facile à étendre.

class Typewriter {
  constructor(element, options = {}) {
    this.element = element;
    this.speed = options.speed || 80;
    this.deleteSpeed = options.deleteSpeed || 40;
    this.pauseTime = options.pauseTime || 1500;
  }

  // Attendre un certain temps
  wait(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  // Écrire un texte caractère par caractère
  async type(text) {
    for (const char of text) {
      this.element.textContent += char;
      await this.wait(this.speed + Math.random() * 50); // Variation pour un effet naturel
    }
    return this;
  }

  // Effacer n caractères
  async delete(count) {
    for (let i = 0; i < count; i++) {
      this.element.textContent = this.element.textContent.slice(0, -1);
      await this.wait(this.deleteSpeed);
    }
    return this;
  }

  // Effacer tout
  async deleteAll() {
    await this.delete(this.element.textContent.length);
    return this;
  }

  // Pause
  async pause(ms) {
    await this.wait(ms || this.pauseTime);
    return this;
  }

  // Boucle sur plusieurs textes
  async loop(texts) {
    while (true) {
      for (const text of texts) {
        await this.type(text);
        await this.pause();
        await this.deleteAll();
        await this.wait(300);
      }
    }
  }
}

// Utilisation simple et lisible
const tw = new Typewriter(document.getElementById('typewriter'), {
  speed: 70,
  deleteSpeed: 30,
  pauseTime: 2000
});

tw.loop([
  'Je crée des sites web.',
  'Je développe des applications.',
  'Je transforme vos idées en code.'
]);

Pourquoi cette version est meilleure

  • Lisible : le chaînage avec async/await lit comme une recette étape par étape
  • Naturelle : Math.random() * 50 ajoute une légère variation de vitesse, comme un vrai humain
  • Extensible : ajoutez facilement des méthodes (highlight(), moveTo(), etc.)
  • Réutilisable : un seul new Typewriter() par élément

Ajouter un curseur CSS personnalisé

Pour un curseur plus réaliste que le simple |, utilisez un ::after pseudo-élément :

#typewriter::after {
  content: '';
  display: inline-block;
  width: 3px;
  height: 1.2em;
  background-color: #333;
  margin-left: 4px;
  vertical-align: text-bottom;
  animation: blink 0.7s step-end infinite;
}

@keyframes blink {
  50% { opacity: 0; }
}

Avec cette approche, pas besoin d’élément HTML supplémentaire pour le curseur.

Exercice : créez votre propre effet

Créez une page HTML avec un effet typewriter qui :

  1. Écrit « Bonjour, je suis  » puis enchaîne avec votre nom en couleur différente
  2. Pause 3 secondes
  3. Efface uniquement votre nom
  4. Écrit votre titre professionnel à la place
  5. Recommence en boucle

Indice : utilisez deux éléments <span> côte à côte — un fixe pour « Bonjour, je suis  » et un dynamique pour le texte qui change. Appliquez la classe Typewriter uniquement sur le span dynamique.

#animation #javascript #texte
Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 350.000 FCFA
Parlons de Votre Projet
Publicité

Articles Similaires