Sequential typing animation using CSSOM, CCS3 and javascript

I was looking for a way to emulate typewriting on multiple paragraphs inside a list, char by char, to solve a problem in my HTML5 implementation of “Space Invaders” (see the tutorial series which deals with its implementation).

The only requirement was use CSS3 (for personal research and fun).

Because of conflicts with my code or browser rendering, I was not satisfied with solutions found online (although really interesting, especially those described by Lea Verou and mayyan14), so I developed my own.

Basically, what we are doing here is strechting the paragraph width through a simple transition, from “0px” to its “offsetWidth”. To emulate the effect of type writing, we split the transition into a discrete number of time steps, equivalent to the number of characters composing the paragraph element. The number will help us also in setting the animation delay on each paragraph.

HTML

HTML is fairly basic: an unordered list of <p> elements, identified by a precise id.

CSS

CSS defines a basic and shared set of properties, which will be applied to the page before any javascript customization.
1. We are using a “Consolas, monospace” font family on <body> to have fixed width for each character.
2. On each <p> we set “display”, “white-space”, and “overflow” properties in order to let the paragraph hide part of its content while animation is running, showing letter by letter.
3. Finally, we set the initial width to “0px” applying the “startTypewrite” class.

Javascript

Now to the interesting part. Basically, we need to add few CSS rules to start the animation. Using the cryptic CSSOM API, we are able to customize them on each paragraph, before we add the rules to the page.

Step 1 adds a “@keyframes” rule to the paragraph, specifyng that the animation should transform its width from “0px” to its “offsetWidth”. For instace, we are declaring the rule “@keyframes text1_typing {from {width: 0} to {width: 110px}}”, associated to first paragraph.

Step 2 sets an “.end” class to stop the animation after each letter, in each paragraph, has been shown. It force the paragraph to retain the width declared by the “to” directive in the previous step.

To obtain a typing animation, we need to show one letter on each animation iteration. Step 1 defines the first (how the animation should starts) and the last (how the animation should stop) states. Consequently we need a way to split the overall animation into a sequence of discrete steps, each of which will add on screen one letter at a time. The css “steps()” function helps in defining the “animation” rule: for instance, we are declaring the rule “animation {text1_typing 2s steps(11, end) 0s}”. This rule asks the browser to apply, for paragraph with id “text1”, the animation named “text1_typing”, run the animation with a 2 seconds duration, split the animation into 11 frames, start the animation after a 0 seconds delay (this delay will be incremented on each paragraph, in order to sequentially show all the paragraphs).

Step 5 defines an event handler to stop the animation and persist the final width on paragraph after the animation has reached its end.

The solution has few drawbacks: it requires monospace fonts, but this was ok with me, because I was working with a retro arcade font; additionally, browser should implement support for CSS3 animations and keyframes.

references