How to Make Text That Writes Itself in Javascript

One of my goals for the new year is to start actually blogging, to share the things that I’m learning, and to keep a better record for myself. To go along with that, I launched a new version of my site with the Fixed Theme from Array Themes. It’s incredibly well balanced, fast as hell, and a pleasure to use.

But I did want to carry over one thing from the last iteration of my site, and that is a sort of typewriter effect on the homepage which has a few messages from me to you. I actually saw this over at Music For Programming, and adapted the code for my own needs. But I thought I’d break down how it works. It’s written in vanilla JavaScript, in about 50 lines of code. The end effect is that text appears to type itself across the screen, delete the words, and then type some more.

Here’s what it looks like in action:

The effect itself is deceptively simple. JavaScript runs through each message, and one by one, pops the last letter off of the a message, and attaches it to the container. When we switch to “delete” mode, the opposite is done. In between running each of these, we add a random delay, then call the function again.

The first part is just about setting some variables. Nothing special here, just getting the value of the initial text with container.innerHTML, creating an array with the messages we want to type out, and setting an initial delay.

Next up, we create a simple updateText function. All this will do will take the value passed to it and update the container div with our new text:

function updateText(txt) {
    container.innerHTML = txt;
}

Now comes the cruft of our code, the “tick” function. The first part of the function checks to see if there is any text in our container div. If it is empty, then we have reached the end of the word. It increments our global variable timer (t), sets the message back to an empty string and switches to “write” mode.

    if(container.innerHTML.length == 0) {
        t++;
        thing = things[t];
        message = '';
        mode = 'write';
    }

Next up we use the JavaScript switch statement to move back and forth between two different modes. Switch simply takes a variable, in this case “mode” and runs code based on which case is set. The first mode is called write, which you’ll notice is what we set our mode to above, when the container is empty.

Our mode uses two crucial JavaScript string functions. The first is slice and the second is substr. Imagine our message is blank, we are starting to type a new line. First, the function uses slice to grab the first word off the beginning of our new message, and adds it to the message variable:

message += thing.slice(0, 1);

Next, it removes the first word off our message. That way, the next time this function is called it will grab the second letter, then third letter, and so on:

thing = thing.substr(1);

The write mode of this function does a few more things. For instance, if we have reached the end of our array, then we clear the window’s timeout function and return. We are done, and we want the last message to simply stay on screen. It also checks if there are any more letters in our message. If there are, it creates a delay that uses Math.rand to generate a random number. By using a random number, the effect has more of a typewriter feel. If you made the delay something static, it would look a lot more robotic. You can play around with the delay a bit to change the effect.

Our “delete” mode is even simpler then write. All we have to do is use slice to grab our message and pull the last word off of it. Then we run updateText() again to update our message, one by one.

  message = message.slice(0, -1);
  updateText(message);

And that’s about it. Our final step is just to kick off the function with an initial setTimeout. This will the delay we declared in our global variable (in this case 1 second), and start the function by deleting the initial message. Keep in mind, that I assigning window.setTimeout to a variable so that when the function is all done, I can use clearTimeout() to remove it altogether.

var timeout = window.setTimeout(tick, delay);

I’m sure there are lots of ways to do this, so I’m definitely open if someone has a different implementation. But I thought it was a cool trick that makes use of pretty common JavaScript string functions. Hopefully, you found it useful.