How to Create a CSS3 Ajax Loading Icon Without Images

642-css3-ajax-spinner

There’s an inevitable delay whenever your web application interacts with the server. That could be for an Ajax request, uploading a file, or using newer HTML5 APIs such as web sockets or server-sent events.
Ideally, you should give the user some feedback to indicate their action is being processed. You’ll often see small animated GIFs with rotating patterns. There are several sites which will create them for you, such as preloaders.net and ajaxload.info.
Images are the best cross-browser option but they have a number of issues:
  • GIFs do not support alpha-transparency. You need to be careful when placing the image on a colored background.
  • Bitmap images won’t scale nicely. If you change the dimensions, you need to create a new image.
  • If you’re not careful, animated graphics can have a large file size.
  • Images incur an additional HTTP request. While the image will be cached, the initial download may take longer than the background process it represents! You can code around this issue by pre-loading the image or using embedded data URLs but it’s more effort.
Fortunately, CSS3 allows us to create loading icons without images. They’re easy to create, scale, re-color, use on any background and don’t incur image downloads. You require:
  1. A single HTML element, e.g. <div id="ajaxloader"></div>.
  2. A few CSS backgrounds, border and shading effects to create a graphical icon.
  3. CSS3 transformations and animations to rotate or move the element.
View the demonstration page…

Browser Compatibility

CSS3 transformations and animations are experimental properties which require vendor prefixes — and you know what trouble they cause. The example code implements the final property as well as prefixes for -webkit (Chrome and Safari), -moz (Firefox), -ms (IE), and -o (Opera), but there’s no guarantee they’ll work consistently if at all.
At the time of writing, recent versions of Chrome, Safari and Firefox offer CSS3 animations. IE9/8/7/6 and Opera show a static image, although IE10 and Opera 12 may support the properties.
Just to complicate matters further, Firefox allows you to animate pseudo elements separately. You can therefore add a couple of elements using :before and :after and rotate or move them in different directions to create more complex animations. While I’d initially hoped to do that, it doesn’t work in the webkit browsers. Chrome and Safari only allow real elements to be animated. It appears to be a bug or oversight, but it’s not been fixed in the current or beta releases.

Creating the Icon

Our HTML div can be placed anywhere in the document although it might be best to append it as the last child of the body. It will then appear above other elements and can be positioned in relation to the page.
The icon CSS simply sets wide white rounded border. The right border color is then set to transparent and a little shading is applied:

#ajaxloader
{
 position: absolute;
 width: 30px;
 height: 30px;
 border: 8px solid #fff;
 border-right-color: transparent;
 border-radius: 50%;
 box-shadow: 0 0 25px 2px #eee;
}
The result:
CSS Ajax icon 1
It’s easy to tweak the properties for different effects, e.g. adding border-right: 0 none; produces:
CSS Ajax icon 2

Animating the Icon

To make the icon spin and pulsate, we apply rotation transformations and opacity changes within a CSS3 animation. The animation name, duration, easing type and repeat are applied to the element:

#ajaxloader
{
 animation: spin 1s linear infinite;
}
followed by the animation keyframes:

@keyframes spin
{
 from { transform: rotate(0deg);   opacity: 0.2; }
 50%  { transform: rotate(180deg); opacity: 1.0; }
 to   { transform: rotate(360deg); opacity: 0.2; }
}
None of the browsers support animation without vendor prefixes so you’ll see -webkit, -moz, -ms and -o alternatives within the source code when you view the demonstration page.
The icon can now be displayed using a little JavaScript whenever an Ajax request is initiated. It’s a great effect which can be customized easily and works on 55% of current browsers.
Unfortunately, 45% of web users won’t see the animation. That number will fall when IE10 is released and users switch to recent versions of other browsers, but it remains a large percentage. You could fall back to an image but, if you’re doing that, you might as well use the image for all browsers.
I therefore suggest you look at your own statistics. If your visitors are are predominately using Chrome, Safari and Firefox you could adopt the technique today. If not, stick with images for now and wait a little longer for more consistent browser support.

Post: How to Create a CSS3 Ajax Loading Icon Without Images