My brain is somewhat fried from thinking about state-management in a Single-Page Application (SPA). As such, I needed a little mental palette cleanser; and, something that I've been wanting to do for a while is try to recreate the "This Is Us" opening titles sequence using CSS animations.
While I use CSS transitions a lot, I don't often think to reach for full-on, multi-step animations. As such, it wasn't immediately clear to me how to animate all three words in the "THIS IS US" opening sequence. Once I realized an animation applies to one element at a time, I created three animations, one for each word.
Not all of the words show upon the screen at the same time. But, in order to keep the mental model simple, I am assuming that all DOM elements will be present. As such, in order to delay the rendering of one word, I simply keep it transparent in the earlier portion of the animation. I feel like this keeps the timing consistent and easy to reason about.
By default, CSS animations run once and then stop. You can define an "animation-iteration-count" property and give it a static number; or, "infinite". But, I didn't want the animation to repeat instantly; I wanted the final rendering to linger on the screen for a few seconds, then disappear for a second, and then - finally - restart.
To do this, I end up programmatically removing the animating DOM elements from the DOM (Document Object Model), waiting a second, and then re-injecting them into the DOM. By removing and then re-adding them, the animation implicitly restarts once the DOM nodes are back in place.
To time this restart sequent, my first instinct was to listen for the "animationend" event. But, this event fires once for each of the animating elements in the title sequent. As such, I ended up going with simple Timers. This just felt like the most straightforward solution.
NOTE: This Timer-based solution does lead to some strange behavior since I believe the Timers (or the animations) don't run consistently when the window is blurred. As such, if you leave the window, then come back some time later, the current animation may be truncated. But, this self-corrects the moment the next animation starts.
With that said, here's the code that I came up with:
At first, I wanted each animating element to be positioned absolutely using percentages. But, I couldn't figure out how to scale the font-size and offsets in-step with the browser dimensions. Unlike a TV, the width and the height of the browser don't have to change in a proportional way. As such, I ended up positioning a percentage-based anchor; then, using absolute pixels to position the individual words. I am sure that I could have used media queries to do this more flexibly; but, I can almost guarantee that it would have been a world more complex.
So see this in action, watch the video. But, here's a screen-shot, mid-animation:
Anyway, this was just a fun little CSS code kata. CSS animations seem extremely powerful. They are definitely a feature of web development that I have to reach for more often.
Want to use code from this post? Check out the license.
At the time I posted this, GitHub was having a major outage. As such, the gist doesn't load consistently; and, I'm pretty sure the
gh-pages branch (which hosts the online demo) isn't building properly. I'll try to get that sorted once the GitHub incident is closed.