IT IS HERE! Get Smashing Node.JS on Amazon Kindle today!
Show Posts
← Back to homepage

APNG provides simple frame-based animation functionality. It’s main goal is solve the problem of animating alpha-transparent images (PNG format).


APNG is very flexible when it comes to the method of displaying the various animation frames.

The default behavior is taking the filename, for example spinner.png, and changing the src or background-image attribute to spinner-2.png, spinner-3.png and so on.

If the useNative functionality is in place, which is set to be on for Firefox 3 and Opera 9.5, the Javascript-based animation is not run. I encourage you to create an actual APNG for the default frame (spinner.png). If you do so, you’ll see increased performance for the browsers that support it -while also promoting the adoption of this new format-, and other browsers will just display the first frame and the animation will run via JavaScript.

You can also use background-position based animations to avoid making multiple requests, and avoid potential cache issues in old browsers.

The APNG class supports dynamic pausing, canceling, resetting and starting of animations. Frames can have a fixed interval or one can be assigned for each of them. Preloading is supported, which can prove useful for long animations or animations that are initialized and not run from the start.

How to use

// new image
img = new Element('img', { src: 'images/zoom-spin.png' }).inject(document.body);
new APNG(img, { useNative: false, frames: 12, endless: false });

// existing images
new APNG('imganimated', { useNative: false, frames: 12, endless: true });

// existing div
new APNG('divspinner', { useNative: false, frames: 12, endless: true, property: 'background-image' });

// existing div, single image
new APNG('divspinner2', { useNative: false, frames: 12, endless: true, property: 'background-position', axis: 'x', interval: [100, 90, 80, 70, 60, 50, 40, 30, 20, 10] } );


* property - (*string*, defaults to 'src') Can be 'src', 'background-image' or 'background-position'. The first two require multiple images, while position a single one that is clipped.
* axis - (*string*, defaults to 'x') If background-position is used, in what direction the position is altered to display the next frame (x or y)
* ext - (*string*, defaults to '.png') The extension of the image, required for multiple images animations.
* frames - (*integer*) The number of frames the animation has.
* endless - (*boolean*, defaults to true) When the last frame is reached, whether the animation stops or restarts.
* interval - (*mixed*, defaults to 100) A single time interval for frames, or an array of intervals, with as many values as frames.
* autoStart - (*boolean*, defaults to true) Whether the animation starts or not when the APNG instance is created.
* startFrame - (*integer*, defaults to 1) The index of the frame displayed first
* preload - (*integer*, defaults to true) If 'src' or 'background-image' are used, preload images. Useful if autoStart is set to false
* useNative - (*boolean*, defaults to true in FF/Opera) Whether to fallback to a file with format {basename}-anim.png if the browser supports real APNGs.
* addFilter - (*boolean*, defaults to true in IE) Whether to add the PNG filter correction for trident.

For the complete documentation and API refer to the Docs directory in the downloaded package.


  • 0.1: First release


This demo showcases the most common and useful scenarios of APNG. The images are taken from FancyZoom.


Fili Wiese said

Sounds good, where is the download button?

So where’s that download package?

Sander said

it works nicely with an iframe!

Ruslan said

I’ve made simple jQuery implementation of this idea —

Your thoughts?

About Guillermo Rauch:

CTO and co-founder of LearnBoost / Cloudup (acquired by Automattic in 2013). Argentine living in SF.