Weblog by Edwin Martin about frontend webdevelopment and related topics

Animate anything in jQuery

I’ve been using jQuery for three years now in several projects and I love it. One of the many reasons I like jQuery is its extensibility. It’s very easy to write your own plugin, your own CSS pseudo selector-like filter or your own easing function.

What’s less known is that you can also customize the animate function. Every jQuery-user knows you can animate all number-based CSS-properties. (Did you know you can also animate scrollTop and scrollLeft?) In this article I explain how to customize the animate function.

Customizing the animation-function is not so hard and gives you a couple of features for free: think about the fx-queue, easing, callbacks and setting the duration.

The first thing I wanted to animate was fading one color to another. It turned out John Resig himself already wrote a plugin to does just that: Color Animations.

Unfortunately, it has a bug which makes the plugin unreliable. To initialize the animation, the plugin checks for fx.state being zero. I turned out that with consecutive calls, the animation can start without fx.state being zero and as a result, the animation not performing.

My next quest was to rewrite the plugin to my liking. I fixed the bug. I added the missing borderColor, so to change the border color, it’s not longer necessary to specify all four borders seperately. I also tried to keep the plugin very small.

Take a look at the result: the Color animation jQuery-plugin.

So how can you make your own custom animation? Just like the other jQuery-customizations, it’s actually quite simple. Take for example the code to animate the background color:

$.fx.step.backgroundColor = function(fx) {
	if (!fx.init) {
		fx.begin = parseColor($(fx.elem).css('backgroundColor'));
		fx.end = parseColor(fx.end);
		fx.init = true;
	} = calculateColor(fx.begin, fx.end, fx.pos);

Give $.fx.step a new property and assign it a function which will handle the animation. This function has one argument, say fx, which belongs to that one animation, so you can use it anyway you like. It has some properties already set. The most important are fx.elem, fx.end and fx.pos. In fx.elem you’ll find the element on which the animation is applied, and in fx.end you’ll find the end-value you want to animate to. fx.pos is a float, going form zero to one during the animation.

In the example above, some initialization is done at the first call of the function in an animation. Here, the begin and end values are calculated. The rest of the functions assigns the calculated value to the CSS-property of the element. The calculation looks like this:

begin + pos * (end - begin)

If the animation is called with the end-value being a string, then fx.end will be that string. So when calling a.animate({color: “#ccc”}), fx.end will be “#ccc”. However, if the string starts with a number then fx.end becomes that number. So when calling a.animate({myProp: “10px 20px”}), fx.end will be 10 and you’ll lose the rest of the string. To get the whole string you should look at fx.options.curAnim.myProp instead of fx.end. In this last example, myProp is a self defined property.

I thought a cool thing to animate is the new shadow CSS-property. A box shadow property consists of several parts: the color, whether it is inset, the x- and y-offset, the blur-radius and the spread-radius. All of these had to be taken into account when writing the plugin.

The result is the Shadow animation jQuery-plugin.

Unfortunately, this plugin does not work in Opera and Internet Explorer. Opera has a strange bug in which you can’t request the current shadow-value. Internet Explorer is miles behind and doesn’t support CSS-shadows. I expect the plugin will work in Internet Explorer 9.

These two animation plugins are the first on my list of jQuery-plugins. It’s my intention more will follow.

Update: a couple of months after this article was published, jQuery 1.4.3 was released, with better support for writing custom CSS-properties and animations. Read more about this technique called jQuery.cssHooks.