Over a year ago I released Sonic, a JavaScript Canvas utility for making loading spinners. I’ve used it in a couple of my own projects and was pleased with the result but I quickly became aware that others may not be happy to:

  • Include a 1.5k JS utility + specific sonic configuration
  • Depend on HTML5 Canvas: lacking browser support & potential performance costs

Not long after releasing Sonic, Github user cadc made SonicGIF, introducing me to a novel concept — converting images in an HTML5 Canvas to an animated GIF on the fly using jsgif.

Fast forward to this week and I’ve been working on a live Sonic editor so you can create spinners using JavaScript, immediately have them converted to GIF, and even a PNG Sprite (example), for you to use via a CSS3 steps Animation.

The spinner you use should be tailored to your needs though. This particular niche of graphic animation is split between various different techniques, each with merits of their own, so choose wisely…

State of spinners 2013

  • GIF
    • Good: simple, widely supported
    • Bad: limited FPS (depends on browser), 256 colours, difficult to change
  • APNG
    • Good: More colors than GIF, 8-bit transparency
    • Bad: Support very limited, difficult to change
  • SVG via <animate>, <animateTransform> etc.
    • Good: Vector based, easily editable
    • Bad: No IE support, continually recalculated [1]
  • SVG via JavaScript
    • Good: Vector based, easily editable, widely supported
    • Bad: Only IE9+, continually recalculated [1]
  • Canvas via JavaScript
    • Good: Widely supported, easily editable, pixel control, can cache rendered frames
    • Bad: Only IE9+, can be slow if frames aren’t cached
  • Sprite animated via JavaScript (i.e. setInterval + mutating backgroundPosition)
    • Good: Widely supported, relatively quick
    • Bad: Little opportunity for browser to optimise, difficult to change
  • DOM+CSS Animated via JavaScript
    • Good: Widely supported, easily editable
    • Bad: Little opportunity for browser to optimise, continually recalculated [1]
  • Sprite animated via CSS3
    • Good: GPU acceleration (depending on browser, device)
    • Bad: Difficult to edit (Sprite), IE9 and below not supported
  • DOM+CSS Animated via CSS3
    • Good: GPU acceleration (depending on browser, device), easily editable
    • Bad: IE9 and below not supported

[1]: By “continually recalculated”, I mean that the animated property values need to be recalculated on each frame and then the corresponding graphic needs to be drawn (even if you cache property values, individual elements need to be drawn for each frame). As far as I know this is unavoidable with traditional JavaScript DOM Animations (including SVG Animations). This is in contrast to Canvas, for example, where you have the opportunity to cache rendered frames and simply re-run them indefinitely.

The graphical capabilities of each technique should also be taken in account. If it’s a straightforward circling snake or dots then you’re probably best going with either SVG or DOM+CSS. If, on the other hand, it’s a more complex animation (e.g. gradients, blur, unique pathing) you may want to venture into Canvas territory or even developing your own PNG Sprite in Photoshop (or Sonic Creator!!). That said, a straightforward GIF may be the best solution if you’re not too fussed about 256 colours, lack of alpha transparency or a lower FPS.

Performance

From limited testing the most performant spinners are those using CSS3, either to animate DOM elements, or to animate through a PNG Sprite. Of course, a single spinner on a page will cost very little, so it’s not necessarily something you need to worry about.

Resources

For CSS+DOM Animation where all you want is a basic spinner (i.e. lines arranged in a circular fashion pulsating with frequency) I suggest using spin.js which utilises CSS3 Animations and falls-back to VML in older versions of IE.

If you do need more control and are happy using either HTML5 Canvas, GIFs or PNG Sprites (with CSS3) then I reckon you should try out Sonic Creator.

Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!