As I test out code changes in my local environment, I always run through this interstitial/waiting page that contains a loading animation. This animation is generally done via an animated .gif, or a .swf movie. Today while waiting for my app to load some backend stuff, it occurred to me that I could pretty easily replicate this same thing in pure HTML + CSS, thus making changes to color or shape super simple.
Here's a screenshot of what I'll be replicating:

NOTE: I'm doing this assuming Chrome browser, and so will be leaning heavily on CSS3, and the -webkit- prefix. At the end of this post, there's a link to site that does a bunch of awesome automated stuff for all this, so I'm eliminating all the complexity for the sake of this talk.
Update: Just added some -moz- support too, though Firefox doesn't animate as nicely as Chrome.
HTML
First, the markup. I figure I'm looking at a div that contains 5 objects. I'm going to call this thing "loader", and each object will just be a span (because they're inline) with a class of "frame" (though I probably don't need a class on these, I wanted to add them for clarity).
So, our HTML markup will look like this:
CSS
Basic Stuff
Let's now add in some basic styling for this thing. I really don't need to do anything with my #loader container, though I certainly could add some margin offsets or whatever I want. But my frames do need some love. I'm starting by defining a light grey background:
.frame {
background: #999;
}
I'm going to set these to display: inline-block, because I want them still inline like spans want to be naturally, but also want them to have the dimension properties of block. I also want to set the size of these to 20px square, and add a right margin to offset them from one another:
.frame {
background: #999;
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
}
That should get us looking like so:

.frame {
background: #999;
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
border-radius: 10px;
opacity: .3;
}

Animation
Alright, now comes the really fun stuff. First, some additional reading as a point of reference: W3Schools.com: CSS3 Animations.
I need to define a name for my animation (sort of like a javascript function; I'll call ours "loader"), a duration for my animation (in this case I want my animation to last one second), and how many times I want this thing to repeat (in our case, I want it to repeat forever):
.frame {
background: #999;
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
opacity: .3;
border-radius: 10px;
-webkit-animation-name: loader;
-webkit-animation-duration: 1s;
-webkit-animation-iteration-count: infinite;
}
Nothing is going to happen yet though because we need to define what, specifically our animation is supposed to DO. Essentially, I want these circles to:
- Fade in/out
- Change color
- Grow slightly
@-webkit-keyframes loader {
0% {}
50% {}
100% {}
}
Now that we have our keyframes for our animation defined, we can define WHAT we want to happen at 0%, 50%, and 100% of our animation. Recalling my list of things I want to do (fade in/out, color change, size change), I'll add those in my keyframes. Note I don't need to define every property of my starting and ending points, because that's handled with our .frame styles we defined earlier. As such, I just need to define how these look in the middle of the animation, in this case opacity of 1, background-color of red, and I want to scale them up just a touch:
@-webkit-keyframes loader {
0% { }
50% { opacity: 1.0;
background-color:red;
-webkit-transform: scale(1.2); }
100% { }
}
Now We have a nice set of circles that all sort of pulse together from slightly transparent light grey to a full opaque and slightly larger red. But we want each of these to sort of follow each other in the animation; that is, we don't want all of them pulsing simultaneously, but rather independently, and one right after the other. I can do this using nth-child selection and a keyframe animation delay for each of my 5 .frame objects. Because my animation is 1 second long, and I have 5 objects, I'll just divide 1/5 and set each animation delay to offset by .2 seconds; that CSS will look like this:
.frame:nth-child(1) {
-webkit-animation-delay:0.2s;
}
.frame:nth-child(2) {
-webkit-animation-delay:0.4s;
}
.frame:nth-child(3) {
-webkit-animation-delay:0.6s;
}
.frame:nth-child(4) {
-webkit-animation-delay:0.8s;
}
.frame:nth-child(5) {
-webkit-animation-delay:1s;
}
Sweeeeeet. Now we're cooking with fire! So, what I've done is just delayed when the animation is supposed to start for each of my .frame objects, and presto - we've replicated our loader.
Changing color or shape
Before, my loading page used either an animated .gif/.swf, which if I wanted to change the color of these circles means I'd have to have extra software, or at the very least spend a little time re-working my graphics so I can output the new file. But now, if we wanted to change this to say, blue and square, all we need to do is edit some CSS:
.frame {
border-radius: 0;
}
@-webkit-keyframes loader {
50% { opacity: 1.0;
background-color:blue;
-webkit-transform: scale(1.2); }
}
Demo
The above demo won't animate unless you're using a Mozilla or Webkit browser
Demo with Full Code (Demo currently works only in Webkit or Mozilla browsers)

