A jQuery function to animate using CSS3 transitions if possible, with the built-in animate fallback.

This requires you to use the amazing Modernizr library, or could be modified to use your own check for whether the browser supports CSS transitions. It’s rough and ready, but works fine as far as I know!

For lots more info and demos of transitions, have a look at my CSS3 transitions and transforms tutorial.

All this lot goes before your document ready section.

var speed = 500; // Default animation speed in milliseconds (1000 = 1 second)

var vP = "";
var transitionEnd = "TransitionEnd";
if ($.browser.webkit) {
	vP = "-webkit-";
	transitionEnd = "webkitTransitionEnd";
} else if ($.browser.msie) {
	vP = "-ms-";
} else if ($.browser.mozilla) {
	vP = "-moz-";
	transitionEnd = "transitionend";
} else if ($.browser.opera) {
	vP = "-o-";
	transitionEnd = "oTransitionEnd";
}

function animate2(object, cssProperties, callback, ms) {
	if (!ms) {
		ms = speed;
	}
	
	if (Modernizr.csstransitions) {
		object.css(vP+"transition", "all "+ms+"ms ease-in-out");
		
		object.css(cssProperties);

		if ($.isFunction(callback)) {
			object.bind(transitionEnd,function(){
			     object.unbind(transitionEnd);
			     callback();
			});
		}
		
	} else {
		if ($.isFunction(callback)) {		
			object.animate(cssProperties, ms, callback);
		} else {
			object.animate(cssProperties, ms);			
		}
	}
}

Then, the bit that runs once the DOM is built:

$(function(){
    // Simplest example. Animate the height of a box to 600px high.
    animate2($("#my_box"), {"height": 600});

    // More complex. Animate the height to 600px, and the left-margin to 100px with a callback.
    animate2($("#my_box"), {"height": 600, "margin-left": 10px}, function(){
         console.log("Animation finished");
    }, 1500);

});

Rather pleasant I feel. I’d really welcome suggestions for improvement, the idea is to provide a simple way to move things around using the best method possible.

15 thoughts on “A jQuery function to animate using CSS3 transitions if possible, with the built-in animate fallback.

  1. All it does is pass it to .animate or .css, so anything that transitions or animate supports will work. Of course, if animate supports something, but transitions doesn’t, then you’d only get an animation in browsers that didn’t support transitions, so you’ll need to test if using unusual properties.

  2. That’s awesome – so if gimmePrefix(‘transition’) is true, then I know I’ve got transitions. Useful to know, though I normally need to test for transitions, transforms, transforms3d and history, as well as enabling HTML5 elements, so Modernizr is usually a good fit.

  3. I can’t help but wonder why you would want to use javascript in order to use css3 transitions though. Is there a hardware/performance benefit to using css transitions vs. jquery animate? With this method either way you need javascript, why not just let the css gracefully degrade?

  4. I was looking for something like this to animate text for iOS. Does this use 3D to utilize hardware acceleration. I am hoping to animate individual text characters and up to 1000s of them. Any thoughts?

  5. Hi Richard,
    I just read your CSS Transitions tutorial and then saw this post here, so I thought I could use it perhaps as the CSS tutorial doesn’t work on FF.
    As I’m not well-versed with javascript, I was wondering where and how I add the scripts above? I already downloaded the Modernizr min.js file and added a line to my test index.html file above the .
    Any help is appreciated!

  6. Anywhere should work, but I’d put it in a script block just before the tag. The tutorial does work in Fx, but it needs to be a recent version. Try Firefox 4 if you want to see what’s going to be coming up in the next version.

  7. Hello Everyone,
    With the help of animate () method we can create animation effects on
    html page
    .In this article I am using animate method to give animation
    effect on image. It
    means image height and width will be resized when mouse pointer
    will over on
    image as shown below……………………………………………………………… for more details check out this link….http://mindstick.com/Articles/464325ac-6ea3-45ca-b308-a063eedf8000/?JQuery%20animate%20method

    Thanks !!!!!!!

  8. I’ve been playing with modifying the >ms+”ms ease-in-out”< to mimic the bounce that is in jquery. I don't know how to get it to work (but I did manage a cubic bezier). Could you offer a hint, or a way to include a keyframe like the arcing one here: http://coding.smashingmagazine.com/2011/09/14/the-guide-to-css-animation-principles-and-examples/ ?

    I would like a direction-less bounce, but can make a separate one for each of the four directions.

  9. Why not turn it into a jQuery plugin? Or perhaps even better – override the normal .animate()-function? That way you’d get rid of those nasty global variables and usage would be more like other jQuery functions.

  10. The issue with this code also becomes that the transitionEnd event is never fired if the style has not changed from the current style of the element.

    I got around this by creating a dummy element setting the css properties of this new element to the css properties passed as an argument. then iterate through those css properties and make sure that the properties on the dummy element (your final css properties you want to animate to) are not the same as the css values already set on the specified object. If they are the same it will invoke the callback immediately.

    function animate2(object, cssProperties, callback, ms) {
    if (!ms) {
    ms = speed;
    }

    if (prefixedProperty) {
    //this checks to make sure that there is somethign to transition to … if not lets manually fire the callback
    //@todo in addition to this we should also fire the callback after a timeout of the duration plus some time for edge cases;
    var dummyElement = document.createElement(‘div’);
    var dummy = $(dummyElement);
    dummy.css(cssProperties);

    var sameCSS = true;
    for(var prop in cssProperties){
    if(dummy.css(prop) != object.css(prop)) {
    sameCSS = false;
    break;
    }
    }

    The reason for the dummy element is to avoid mixed css units where as when you use the $.fn.css method it will convert to pixels for css measurements.

    Other suggestions to get around this issue involve setting a Timeout to invoke the callback some time after the duration of the animation to account for these cases. The problem here is that this will add a noticeable delay to the time your callback is fired.

    Don’t know if this is the best way to fix this problem but it is how I solved it.

  11. Bro if you are going to write a tutorial on scripting techniques, use more simple examples so people can scan over. .

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>