Taking CSS Animations to the Danger Zone
Will Hutchinson (@tetowill)
april 8th, 2015
Lately I’ve been wanting to experiment a little more with CSS animations. I already use them for small effects, but to really get to know something, I need a project. A while back I was watching one of my favorite cartoons, Archer, and as the title sequence was rolling I realized, “this would make an awesome CSS animation project!”
Whenever you try to recreate something, it’s best to study the original. A quick search led me to Art of the Title a site dedicated to title sequences. Lucky for me, they have the Archer title sequence posted for our viewing pleasure. Have a look at it to see the sequence I’m building towards.
We Need a Plan
Before jumping into any project, it’s always good to lay out a plan. After studying the original title sequence, I decided I could really do this project. I didn’t think it would be too difficult because it’s all solid colors (e.g., no gradients and patterns), most of the shapes can be created using CSS, and even the more complex silhouettes are not very detailed. All of the animations are pretty straightforward.
First, I broke the entire sequence down into a few separate scenes based on the major transitions. This helped me understand what elements to group together and also gave me some specific goals. I did this by sketching out the scenes:
After that, I took screenshots of all the different layouts in the sequence (51 in total). I put them into Photoshop so I could grab the dimensions, positioning and color of each element. Once I had all this documented, I started setting up my HTML and CSS.
If you just can’t wait, you can view the completed animation at the end of this post, then come back to finish reading.
Structure
I laid out the HTML to separate the individual scenes. There is one element that moves through every scene: the white dot. Since the white dot is not tied to any particular scene, I placed it on the main stage where it is free to move on its own. You’ll also notice that there are seven scenes listed below but eight shown in the above sketch. After the initial planning, I realized that scene two and three from the initial sketch were better off combined.
<div class="wrap">
<div class="main">
<div class="dot"></div>
<div class="scene-1"><!-- elements --></div>
<div class="scene-2"><!-- elements --></div>
<div class="scene-3"><!-- elements --></div>
<div class="scene-4"><!-- elements --></div>
<div class="scene-5"><!-- elements --></div>
<div class="scene-6"><!-- elements --></div>
<div class="scene-7"><!-- elements --></div>
</div>
<!-- END .main -->
</div>
<!-- END .wrap -->
Getting Animated
Once I laid out the first scene, I began setting up the animations. To create timed animations for something like this in CSS, we have to use keyframes. To keep things DRY, I’ll send you over to Chris Coyier’s CSS-Tricks site for more details on the keyframe syntax.
Timing
Keyframe animations use percentages (0-100%). The timing of each
percentage point is based on the duration you set for the animation in
CSS. The entire Archer title sequence is 30 seconds. Since the white
dot exists through the entire sequence, I set its animation for 30s,
which breaks down to 0.3s for each percent. Using that math, it was
helpful to set up some of the shorter animations that align with the
dot for 3s, since that breaks down to 0.3s for every 10%. Easing
(called timing-function
) also plays a part in syncing up multiple
animations. Setting most of the animations to a linear easing worked
out well for this project.
@keyframes theDot {
0% {
/* start properties */
}
50% {
/* other states inbetween */
}
100% {
/* end properties */
}
}
.dot {
animation: theDot linear 30s 0s forwards;
/* animation: <name> <timing-function> <duration> <delay> <fill-mode>; */
}
Steps Function
For most of the animations I used the basic syntax shown above. I
adjusted various properties, such as position and rotation, for the
desired result. However, for a couple of the more robust silhouette
animations (e.g., Lana lifting her gun and Archer running from Lana’s
shot), I set up spritesheets and used the steps()
timing function.
You’ll see that these animations aren’t as smooth as some of the
others. This is because I only broke them down into a couple of steps.
As with any sprite-based animation, having more frames allows for
subtler changes between each, making for a smoother experience.
See the Pen myQmoQ by Will Hutch (@tetowill) on CodePen.
Using the steps
function works well in certain circumstances, but
sometimes the desired effect is much easier with separate images
(e.g., Cyril on the phone and Malory drinking). Creating a spritesheet
for these animations would have taken longer and not been as smooth.
That being said, the only reason I was able to use separate images is
because they do not need to be transparent. If they did need to be
transparent, the images’ overlap would shine through. You can view
this for yourself by adding an opacity to the images in the CodePen
below.
See the Pen jEQwbq by Will Hutch (@tetowill) on CodePen.
Tricks
One of the trickier pieces of this animation was the white dot cutting through the background on certain scenes. I decided the best way to mimic this was to set up a black trail coming off of the dot. Syncing up the trail length and the forward motion, so that the end of the trail wasn’t visible, took some tweaking. In the end I think this was the easiest solution.
See the Pen KwGLOM by Will Hutch (@tetowill) on CodePen.
Helpful Tools
As you can imagine, syncing things gets tedious and I had to make a lot of adjustments to fine-tune things. Luckily, I (and the rest of the front-end team here at Infinity) recently attended the Smashing Conference in Whistler where Paul Irish demonstrated that Chrome Canary had some new developer tools for CSS animations. These new tools allow you to pause and adjust the speed of the animations playing on the page. Being able to slow down the animations to a tenth of the normal speed was a huge help in syncing up the timings of different animations.
Another feature I hope the Chrome team will add is a scrubber for moving backwards and forwards through animations. Even just a couple seconds back and forth would be awesome. There is no rewind functionality with keyframe animations, so once you go past your mark, you have to run through it all again to get back.
Staying Sane
Obviously, there are a few graphics and animations that I had to simplify in order to get this set up in a timely manner and keep my sanity, but that’s to be expected. For example, I didn’t attempt the moving graphics in the backgrounds. Those were just too detailed to recreate. If I were going to add those, I’d redo the two silhouette animations I created using separate images to make them stepped sprite animations instead. That way, I could lower the opacity to have the background graphics show through without the overlapping issue.
I also did all my testing in Chrome and Canary to keep things easy. I thought it best not to go down the rabbit hole of cross-browser compatibility since I wanted to get this finished without cursing too much.
Final Thoughts
CSS keyframe animations are powerful but I think they are better suited for sequences shorter than this. The percentage system implemented by keyframe animations makes adjusting timing and syncing multiple animations tedious. As a follow up, I plan to recreate this again using a JavaScript animation library, such as GreenSock. That way we can compare the two both in terms of output quality and in effort required.
End Result
I guess it’s about that time. Let’s take a look to see what’s been accomplished. Just scroll down and click play. All in all, not too bad if I may say so myself! Perhaps I’ll fine tune it a bit more for the JS follow-up. For those of you who want to dig deeper, this entire project is available on GitHub.
Tags: technology css animation