Animation in a Flashless world
When I splashed down in web design four years ago, the first thing I wanted to do was animate a cartoon in the browser. I’d been drawing comics for years, and I’ve wanted to see them come to life for nearly as long. Flash animation was still riding high, but I didn’t want to learn Flash. I wanted to learn JavaScript!
Sadly, animating with JavaScript was limiting and resource-intensive. My initial foray into an infinitely looping background did more to burn a hole in my CPU than amaze my friends (although it still looks pretty cool). And there was still no simple way to incorporate audio. The browser technology just wasn’t there.
Things are different now. CSS3 transitions and animations can do most of the heavy lifting and HTML5 audio can serve up the music and audio clips. You can do a lot without leaning on JavaScript at all, and when you lean on JavaScript, you can do so much more!
In this project, I’m going to show you how to animate a simple walk cycle with looping audio. I hope this will inspire you to do something really cool and impress your friends. I’d love to see what you come up with, so please send your creations my way at rachelnabors.com!
Note: Because every browser wants to use its own prefixes with CSS3 animations, and I have neither the time nor the space to write all of them out, I will use the W3C standard syntaxes; that is, going prefix-less. You can implement them out of the box with something like Prefixfree, or you can add prefixes on your own. If you take the latter route, I recommend using Sass and Compass so you can focus on your animations, not copying and pasting.
The walk cycle
Walk cycles are the “Hello world” of animation. One of the first projects of animation students is to spend hours drawing dozens of frames to complete a simple loopable animation of a character walking.
Most animators don’t have to draw every frame themselves, though. They draw a few key frames and send those on to production animators to work on the between frames (or tween frames). This is meticulous, grueling work requiring an eye for detail and natural movement. This is also why so much production animation gets shipped overseas where labor is cheaper.
Luckily, we don’t have to worry about our frame count because we can set our own frames-per-second rate on the fly in CSS3. Since we’re trying to impress friends, not animation directors, the inconsistency shouldn’t be a problem. (Unless your friend is an animation director.)
This is a simple walk cycle I made of my comic character Tuna for my CSS animation talk at CSS Dev Conference this year:
The magic lies here:
animation: walk-cycle 1s steps(12) infinite;
Breaking those properties down:
animation: <name> <duration> <timing-function> <iteration-count>;
walk-cycle is a simple @keyframes block that moves the background sprite on .tuna around:
@keyframes walk-cycle {
0% {background-position: 0 0; }
100% {background-position: 0 -2391px;}
}
The background sprite has exactly twelve images of Tuna that complete a full walk cycle. We’re setting it to cycle through the entire sprite every second, infinitely. So why isn’t the background image scrolling down the .tuna container? It’s all down to the timing function steps(). Using steps() let us tell the CSS to make jumps instead of the smooth transitions you’d get from something like linear. Chris Mills at dev.opera wrote in his excellent intro to CSS3 animation :
Instead of giving a smooth animation throughout, [
steps()] causes the animation to jump between a set number of steps placed equally along the duration. For example,steps(10)would make the animation jump along in ten equal steps. There’s also an optional second parameter that takes a value ofstartorend.steps(10, start)would specify that the change in property value should happen at the start of each step, whilesteps(10, end)means the change would come at the end.
(Seriously, go read his full article. I’m not going to touch on half the stuff he does because I cannot improve on the basics any more than he already has.)
The background
A cat walking in a void is hardly an impressive animation and certainly your buddy one cube over could do it if he chopped up some of those cat GIFs he keeps using in group chat. So let’s add a parallax background! Yes, yes, all web designers signed a peace treaty to not abuse parallax anymore, but this is its true calling—treaty be damned.
And to think we used to need JavaScript to do this! It’s still pretty CPU intensive but much less complicated. We start by splitting up the page into different layers, .foreground, .midground, and .background. We put .tuna in the .midground.
.background has multiple background images, all set to repeat horizontally:
background-image:
url(background_mountain5.png),
url(background_mountain4.png),
url(background_mountain3.png),
url(background_mountain2.png),
url(background_mountain1.png);
background-repeat: repeat-x;
With parallax, things in the foreground move faster than those in the background. Next time you’re driving, notice how the things closer to you move out of your field of vision faster than something in the distance, like a mountain or a large building. We can imitate that here by making the background images on top (in the foreground, closer to us) wider than those on the bottom of the stack (in the distance).
The different lengths let us use one animation to move all the background images at different rates in the same interval of time:
animation: parallax_bg linear 40s infinite;
The shorter images have less distance to cover in the same amount of time as the longer images, so they move slower.

Let’s have a look at the background’s animation:
@keyframes parallax_bg {
0% {
background-position: -2400px 100%, -2000px 100%, -1800px 100%, -1600px 100%, -1200px 100%;
}
100% {
background-position: 0 100%, 0 100%, 0 100%, 0 100%, 0 100%;
}
}
At 0%, all the background images are positioned at the negative value of their own widths. Then they start moving toward background-position: 0 100%. If we wanted to move them in the reverse direction, we’d remove the negative values at 0% (so they would start at 2400px 100%, 2000px 100%, etc.). Try changing the values in the codepen above or changing background-repeat to none to see how the images play together.
.foreground and .midground operate on the same principles, only they use single background images.
The music
After finishing the first draft of my original walk cycle, I made a GIF with it and posted it on YTMND with some music from the movie Paprika, specifically the track “The Girl in Byakkoya.” After showing it to some colleagues in my community, it became clear that this was a winning combination sure to drive away dresscode blues. So let’s use HTML5 to get a clip of that music looping in there!
Warning, there is sound. Please adjust your volume or apply headphones as needed.
We’re using HTML5 audio’s loop and autoplay abilities to automatically play and loop a sound file on page load:
<audio loop autoplay>
<source src="http://music.com/clip.mp3" />
</audio>
Unfortunately, you may notice there is a small pause between loops. HTML5 audio, thou art half-baked still. Let’s hope one day the Web Audio API will be able to help us out, but until things improve, we’ll have to hack our way around these shortcomings.
Turns out there’s a handy little script called seamlessLoop.js which we can use to patch this. Mind you, if we were really getting crazy with the Cheese Whiz, we’d want to get out big guns like sound.js. But that’d be overkill for a mere loop (and explaining the Web Audio API might bore, rather than impress your friends)!
Installing seamlessLoop.js will get rid of the pause, and now our walk cycle is complete.
(I’ve done some very rough sniffing to see if the browser can play MP3 files. If not, we fall back to using .ogg formatted clips (Opera and Firefox users, you’re welcome).)
Really impress your friends by adding a run cycle
So we have music, we have a walk cycle, we have parallax. It will be a snap to bring them all together and have a simple, endless animation. But let’s go one step further and knock the socks off our viewers by adding a run cycle.
The run cycle
Tacking a run cycle on to our walk cycle will require a third animation sequence: a transitional animation of Tuna switching from walking to running. I have added all these to the sprite:

Let’s work on getting that transition down. We’re going to use multiple animations on the same .tuna div, but we’re going to kick them off at different intervals using animation-delay—no JavaScript required! Isn’t that magical?
It requires a wee bit of math (not much, it doesn’t hurt) to line them up. We want to:
- Loop the walk animation twice
- Play the transitional cycle once (it has a finite beginning and end perfectly drawn to pick up between the last frame of the walk cycle and the first frame of the run cycle—no looping this baby)
- RUN FOREVER.
Using the pattern animation: <name> <duration> <timing-function> <delay> <iteration-count>, here’s what that looks like:
animation:
walk-cycle 1s steps(12) 2,
walk-to-run .75s steps(12) 2s 1,
run-cycle .75s steps(13) 2.75s infinite;
I played with the times to get make the movement more realistic. You may notice that the running animation looks smoother than the walking animation. That’s because it has 13 keyframes running over .75 second instead of 12 running in one second. Remember, professional animation studios use super-high frame counts. This little animation isn’t even up to PBS’s standards!
The music: extended play with HTML5 audio sprites
My favorite part in the The Girl in Byakkoya is when the calm opening builds and transitions into a bouncy motif. I want to start with Tuna walking during the opening, and then loop the running and bounciness together for infinity.
- The intro lasts for 24 seconds, so we set our 1 second walk cycle to run for 24 repetitions:
walk-cycle 1s steps(12) 24 - We delay
walk-to-runby 24 seconds so it runs for .75 seconds before… - We play
run-cycleat 24.75 seconds and loop it infinitely
For the music, we need to think of it as two parts: the intro and the bouncy loop. We can do this quite nicely with audio sprites: using one HTML5 audio element and using JavaScript to change the play head location, like skipping tracks with a CD player. Although this technique will result in a small gap in music shifts, I think it’s worth using here to give you some ideas.
// Get the audio element
var byakkoya = document.querySelector('audio');
// create function to play and loop audio
function song(a){
//start playing at 0
a.currentTime = 0;
a.play();
//when we hit 64 seconds...
setTimeout(function(){
// skip back to 24.5 seconds and keep playing...
a.currentTime = 24.55;
// then loop back when we hit 64 again, or every 59.5 seconds.
setInterval(function(){
a.currentTime = 24.55;
},39450);
},64000);
}
The load screen
I’ve put it off as long as I can, but now that the music and the CSS are both running on their own separate clocks, it’s imperative that both images and music be fully downloaded and ready to run when we kick this thing off. So we need a load screen (also, it’s nice to give people a heads-up that you’re about to blast them with music, no matter how wonderful that music may be).
Since the two timers are so closely linked, we’d best not run the animations until we run the music:
* { animation-play-state: paused; }
animation-play-state can be set to paused or running, and it’s the most useful thing you will learn today.
First we use an event listener to see when the browser thinks we can play through from the beginning to end of the music without pause for buffering:
byakkoya.addEventListener("canplaythrough", function () { });
(More on HTML5 audio’s media events at HTML5doctor.com)
Inside our event listener, I use a bit of jQuery to add class of .playable to the body when we’re ready to enable the play button:
$("body").addClass("playable");
$("#play-me").html("Play me.").click(function(){
song(byakkoya);
$("body").addClass("playing");
});
That .playing class is special because it turns on the animations at the same time we start playing the song:
.playing * { animation-play-state: running; }
The background
We’re almost done here! When we add the background, it needs to speed up at the same time that Tuna starts running. The music picks up speed around 24.75 seconds in, and so we’re going to use animation-delay on those backgrounds, too.
This will require some math. If you try to simply shorten the animation’s duration at the 24.75s mark, the backgrounds will, mid-scroll, jump back to their initial background positions to start the new animation! Argh! So let’s make a new @keyframe and calculate where the background position would be just before we speed up the animation.
Here’s the formula:
new 0% value = delay ÷ old duration × length of image
new 100% value = new 0% value + length of image
Here’s the formula put to work on a smaller scale:
Voilà! The finished animation!
I’ve always wanted to bring my illustrations to life. Then I woke up one morning and realized that I had all the tools to do so in my browser and in my head. Now I have fallen in love with Flashless animation.
I’m sure there will be detractors who say HTML wasn’t meant for this and it’s a gross abuse of the DOM! But I say that these explorations help us expand what we expect from devices and software and challenge us in good ways as artists and programmers. The browser might not be the most appropriate place for animation, but is certainly a fun place to start.
There is so much you can do with the spec implemented today, and so much of the territory is still unexplored. I have not yet begun to show you everything. In eight months I expect this demo will represent the norm, not the bleeding edge. I look forward to seeing the wonderful things you create.
(Also, someone, please, do something about that gappy HTML5 audio looping. It’s a crying shame!)



Comments
Comments are ordered by helpfulness, as indicated by you. Help us pick out the gems and discourage asshattery by voting on notable comments.
Got something to add? You can leave a comment below.
18/12/2012
Hi Rachel,
The new W3C Web Animation API will give developers cool new features such as media synchronization so you won’t have to use nasty JS timers hacks.
Another way to create a parallax effect would be to use a translateZ() transform to arrange your layers on the Z axis and animate the perspective origin. You will get a “true” parallax since this is created on a real 3D model, no more guess work and approximation.
Cool stuff, thanks.
Vote Helpful or Unhelpful
07/12/2012
@KEV ADAMSON
Adobe’s Edge and Animate products, while having lovely interfaces, produce subpar output, as you said. JS-based animations chew up CPU faster than CSS-based ones, making these tools two years too late and thus not fit for production use. I’d recommend using Flash w/ fallback over using them if you don’t want to or are not capable of hand-coding.
Hopefully some day someone will create a program that gives you a user interface to love and output that keeps up with the rate of change. (Right now, for instance, CSS animation output with a feature detect to a jQuery animate() fallback.)
Until then, people who hand code animations will be able to reap big rewards for making things that work on iDevices. The techniques and technologies are only getting better and faster.
My prediction is that the call for web-based Flash animation will continue to shrink like Florida’s coastline under the assault of rising sea levels. However, using Flash animation to produce full-length animations like “My Little Pony: Friendship is Magic” will continue at its normal pace. The people at Adobe are moving Flash toward a cinematic tool and away from web production. (A Flash animated film can be embedded as a video file on a web page without needing a special plugin to play!)
In the interim, we’ll see animations being used mostly for decorative elements that look fine static as a last ditch fallback.
That said, I can’t wait to see how right or wrong I am two years from now!
Vote Helpful or Unhelpful
06/12/2012
Hi Rachel
I’ve recently created this: http://www.kevadamson.com/demos/big_free_world/animation.html
I used Adobe Edge, which I’m impressed with as a program (very much like Flash, so a familiar UI), although I’m not overly convinced of the code output.
In hindsight, I think I would have created this animation in Flash using vectors. Reasons being:
* The only browser that seems to render the movement smoothly is IE9
* It eats CPU. I wanted to go CSS so it would work on all devices, but while they have the support, they don’t have the power to run it smoothly
* It’s file size heavy for what it is – SVG would probably be better for images, but support and render quality seems inconsistent
I realise I could save file size with slightly better image optimisation, and it might also be the case that the code Edge renders is sloppy, but I went through the same processes with Edge as I used to with Flash, and it rendered something that, in real-terms, is inferior. So perhaps it’s a combination of:
a) Edge not being quite ready yet and
b) CSS animation not being quite ready yet and
c) My knowledge of the best ways to create the effects, not being quite ready yet :)
With Flash I could almost guarantee a playback quality across all browsers (that have Flash installed of course ;)) and merely have an image fall-back for the apple devices and users without Flash. That just feels tidier and a safer option – certainly for client work.
I guess my point is that CSS animation is the future, and it is certainly great for basic transitions on websites or apps built for use on specific devices / browsers (where you can guarantee SVG support and smooth rendering). I think you can also get the best out of it if you hand-code, as it seems different methods of creating the same effect have a massive difference on file size and render quality. But until I can use a program like Edge in much the same way as I used the Flash program, and create an animation with the same file size and consistent render quality as the SWF output, I can’t see myself using it just yet for stand-alone narrative animations for client work.
Would you agree? Do you have any thoughts on Edge?
Vote Helpful or Unhelpful
21/12/2012
It’s great to be reaffirmed about how much can be done with CSS3 now. Thank you for your time for doing these beautiful examples.
I love the sound of ‘flashless’ and ‘browser empowered’ animations. A passionate front-end developer must wish to experience working on projects that embrace such techniques.
Arguably majority of future friendly work happens for mobile devices. Project teams strive to release a product that works faster than ever before. Which puts these techniques under a whole bunch of limitations as where and when they can be used. I would limit this for a smart ‘preloader’ and ‘progress bar’ animations (preferably without an image request).
Vote Helpful or Unhelpful
06/12/2012
I love the idea of keyframes but haven’t had the chance to use them practically yet, I really like their use in this site http://visitbruges.be/home. I’m sure there’ll come at time when the animation techniques will be used more often, perhaps when html5 games begin to develop more but a great technique to know nonetheless. Great article and love your writing style.
Vote Helpful or Unhelpful
09/12/2012
http://www.adobe.com/devnet/createjs/articles/using-flash-pro-toolkit-createjs.html
Although many features unavailable (even motion paths) presumably this will.be Flash’s latest lifeline. Flash was saved almost 10 years ago by video, while the last few years it’s a fallback for older browsers. CS7/8 will most likely see Flash producing less js and more css3 animations… Just look at Fireworks (although they make out gradients and rounded edges are ‘difficult’ to code!). Bring able to handcode can always make your code slicker, but this may just be editing your uncompressed output code rather than typing Matrix style into NotePad. I learned to handcode HTML years ago, and older iterations of DreamWeaver (and other WYSIWYG editors) would bloat pages with masses of redundant code. It’s likely that tools will get better as HTML 5 becomes standard and we can forget older browsers… But I’d almost put money on Flash becoming the defacto web animation tool, again.
Vote Helpful or Unhelpful
10/12/2012
I’m impressed at what can be done with CSS nowadays – without any frameworks and not that much code.
Unfortunately, the final example is not working for me. The frames must not be offset correctly because it looks sort of like old film tape. This screenshot explains it better: http://i.imgur.com/z0uaE.png
I am using Safari 5.1.7 on OS X 10.6.8.
Vote Helpful or Unhelpful
14/12/2012
I’ve just done a boat load of christmas e-card animations for clients. This year is the first year where there has been a lot of demand to do them in ‘html5’ and to ‘make it mobile compatible’. In many cases, once they have had it explained that the cost will be a lot higher, the end result will be a lot simpler and have less shine (e.g no particle effects, blending modes, accurately synced sound, 3d, that it won’t work on old browsers typical in corporate environments and will work poorly on mobiles) they have reverted back to flash which has a far better ROI and quality of result. Unfortunately articles like these stokes hipsters and the blogotwittersphere with the end result that creative directors and account handlers and other assorted people with an eye on fashion, but with no real handle on the reality in the trenches, are doing clients a disservice. Totally agree with Mparaiso!
Vote Helpful or Unhelpful
19/12/2012
How many HTTP requests do you need to have this running? What is the overall size of files and their synchronization? How easy is it for you to change something or add something a week after the animation is done and released? How long does it take to create the animation in general? Do you need complex battery draining animation on your unplugged device?
Most of those answers would be in favor of flash, which is on (as stated in comments above) most computers worldwide. ROI (or value, you get for your time spent on a project) for HTML5/CSS3 is very bad and makes it possible only for some very easy non-reusable tasks and animations.
Anyway, the cat drawing is nice .. :)
Vote Helpful or Unhelpful
09/12/2012
You will obtain better result for ‘flash-disabled’ device with animated gif
For example this animation don’t work in the mobile wolrd. (slow and buggy on Android)
Btw it’s easier and faster to do :
1) build your art in Flash IDE
2) export to .gif
2bis) export to html 5 (canvas) (same perf issue)
The truth is css3 animation or canvas animation use far more cpu than Flash based one.
Vote Helpful or Unhelpful
06/12/2012
Great article and detail on flashless animation. While I haven’t done animations in the past I could see using this in subtle ways for specific projects. Very interesting. Thanks for putting this together.
Vote Helpful or Unhelpful
10/12/2012
@Rachel Nabors
Thanks for confirming my suspicions :)
I’m fine hand-coding basic transitions, but anything more complex is inappropriately time consuming.
I’m looking forward to the tool that gets the balance right.
@mparaiso
Yep. You make some interesting points to consider.
Vote Helpful or Unhelpful
09/12/2012
@RACHEL
Great article!
Is it OK for me to translate it into Arabic and post it on my blog (referencing this one, of course!)?
—-
@mparaiso
I love and respect the work that Flash does, and I think it’s still very usable for certain areas.
However, as far as the web goes, I can certainly see Flash losing ground for a bunch of good reasons.
As for performance, I kept this page in an open tab on Firefox (with the animations running) for the last 5 hours and had to problem whatsoever.
Just a friendly response :)
Vote Helpful or Unhelpful
11/12/2012
For people having trouble viewing on mobile and the odd browser, I’m banking that has to do with Prefixfree, which uses JavaScript to re-write the CSS w/ appropriate syntax prefixes into the document head. It’s not perfected yet, but it kept the markup clean for demo purposes.
For production, I recommend using Compass and Sass to precompile all of your animation styles.
This can definitely be done right on mobile. It just requires more finess than I had time for. Maybe next year there will be a “cartoons for mobile devices with HTML5 and CSS3” article!
Vote Helpful or Unhelpful
07/12/2012
@KEV ADAMSON
I have a solution for you : dont use half-backed techs like CSS animations. While CSS transforms are great ( and some browsers support GPU acceleration for CSS transforms ). CSS animation is a joke, a standard one , but unusable.
Adobe Edge tries to do too much things at once and it does it the wrong way , so it is not a solution , neither.
The solution is simple :
- on desktop , flash is still at a 95 penetration rate , there is no reason not to use it. The alternative is a slow , heavy hard to work with , CPU hog , CSS animation standard.
- on tablets , either provide a simple image as a fallback , or a video , if the the stuff is animation heavy ( but no interactivity … ).
-on mobile : dont bother …
HTML5 did not kill and will not kill flash. People still use it , and dont give a damn about the tech used. You just need to explain your clients that different devices means different experiences.
If you are on Mac , you can test Hype instead of Adobe Edge ,i’m working on a HTML5 animation product focused on optimisation an performance too, and it will be a webapp.
Vote Helpful or Unhelpful
06/12/2012
Thank you, Rachel, for this tutorial. Many things are now solved.
Vote Helpful or Unhelpful
Impress us