Note6 minute read

'Magic' text written automatically with JavaScript

A JavaScript typing-effect experiment to understand timing and UI updates.

  • frontend
  • javascript
  • animation

"Blazes, heretic! Are you telling me the words will appear on their own? Is this sorcery, or witchcraft?"

Confia

It's not magic. It's JavaScript. Let's break it down:


First, we need an HTML element to receive the spell, I mean, the generated text. A paragraph (p) or a heading (h1, h2...) works fine. It just needs to hold text and have an id. Remember: the id must be unique on the page.

<h1 id="magic-text"></h1>

For our case, we'll use an h1 with the id magic-text.


Next, we create and import the JavaScript file. In our example, that's script.js:

<script src="script.js"></script>

In script.js, we create a constant to interact with our h1, using querySelector, which lets us select elements with the same selectors we use in CSS.

In our case, we use the id prefixed with #.

const magicTextHeader = document.querySelector('#magic-text');

querySelector works on the document or on any element after it's declared, selecting its children.


Next, we create a constant with the text to display:

const text = 'Texto inserido automagicamente com JavaScript!';

Finally, we declare a variable to help us "walk through" the text:

let indexCharacter = 0;

The function that renders the text is writeText():

function writeText() {
  magicTextHeader.innerText = text.slice(0, indexCharacter);
  indexCharacter++;
  if(indexCharacter > text.length - 1) {
    setTimeout(() => {
      indexCharacter = 0;  
    }, 2000);
  }
}

On the first line, we set the innerText of the h1 using .slice(), which walks through our text constant character by character, as if it were an array. The .slice() syntax is .slice(a,b), where a is the start index and b is the end index of the slice. Since we want the text from the beginning, we start at 0 and end at indexCharacter, which gets incremented on the next line. Each run of the function adds one more character.

Then we use a conditional to check if indexCharacter has reached the last position in the text (text.length - 1; since the first index is 0, the last one is the text length minus 1). When that's true, indexCharacter resets to 0 after a setTimeout of 2000 milliseconds, so the text starts "typing" from the beginning again.


To run this function continuously, keeping indexCharacter incrementing and the typing effect going, we use setInterval to call writeText every 100 milliseconds:

setInterval(writeText, 100);

And that's the whole trick.


Live demo: g31-magic-text.vercel.app. Code: GitHub repo.

Inspired by this Florin Pop video.