Simpler CSS typing animation, with the ch unit

A while ago, I posted about how to use steps() as an easing function to create a typing animation that degrades gracefully.

Today I decided to simplify it a bit and make it more flexible, at the cost of browser support. The new version fully works in Firefox 1+ and IE10, since Opera and WebKit don’t support the ch unit and even though IE9 supports it, it doesn’t support CSS animations.

To put it simply, one ch unit is equivalent to the width of the zero (0) character of the font. So, in monospace fonts, it’s equivalent to the width of every character, since every character has the same width.

In the new version, we don’t need an obscuring span, so no extra HTML and it will work with non-solid backgrounds too. Also, even though the number of characters still needs to be hard-coded, it doesn’t need to be hardcoded in the animation any more, so it could be easily done through script without messing with creating/modifying stylesheets. Note how each animation only has one keyframe, and takes advantage of the fact that when the from (0%) and to (100%) keyframes are missing, the browser generates them from the fallback styles. I use this a lot when coding animations, as I hate duplication.

In browsers that support CSS animations, but not the ch unit (such as WebKit based browsers), the animation will still occur, since we included a fallback in ems, but it won’t be 100% perfect. I think that’s a pretty good fallback, but if it bothers you, just declare a fallback of auto (or don’t declare one at all, and it will naturally fall back to auto). In browsers that don’t support CSS animations at all (such as Opera), the caret will be a solid black line that doesn’t blink. I thought that’s better than not showing it at all, but if you disagree, it’s very easy to hide it in those browsers completely: Just swap the border-color between the keyframe and the h1 rule (hint: when a border-color is not declared, it’s currentColor).

Edit: It appears that Firefox’s support for the ch unit is a bit buggy so, the following example won’t work with the Monaco font for example. This is not the correct behavior.


  • Dorian_bartsch

    In this sample it failed. Because every character must have the same width.

    • Cedriking

      Yes you’re right!

      • Lea Verou

        Please check my edit. 

    • Lea Verou

      Every character does have the same width, when we’re talking about monospace fonts. That’s why they’re called monospace (or fixed width).

      • Thaddee Tyl

        Would that work with tabs? ;)

  • Kurtextrem

    Its working here – android / galaxy nexus

  • Peter van der Zee

    Oh nice. Must add that to zeon instead of the js hack now.

  • Anonymous

    Works in chrome…

    • Ben

      yeah, it does work in chrome. But the blinking caret covers the characters oddly in places. To really polish this up cross-platform you need to finesse the start and finish points…

  • Blog Freakz

    This one really works fine for me thanks for sharing it .. it works perfectly

  • Nickerson

    This didn’t work for me at all….it worked in this example, but when the code was copied+pasted, it wouldnt work in Webkit, Moz, or Opera. /shrug

    • Lea Verou

      You are forgetting the prefixes or a library that adds them. /shrug

  • Pingback: Chrome 27 Beta: A Speedier Web and New HTML5 Forms | ChromeBytes

  • vishal

    thanks it is amazing…

  • Pingback: Chrome 27 Beta: A Speedier Web and New HTML5 Forms - InfoLogs