CSS3 vs jQuery Animations

Introduction

Flash originally paved the way for us to feature more than just text and images on web pages. It allowed developers to include animations and other rich effects on web pages, leading to a much more colourful and varied user experience. However, Flash was plagued by a number of issues like security, long loading times on mediocre networks, etc. Then came JavaScript libraries like jQuery, Prototype and MooTools, which got around a lot of Flash's issues by running natively in the browser, plus they made it easier for the average developer to use JavaScript to create rich effects and animations. Fast forward a few more years, and we've now got animation capabilities available in CSS3, which offers additional advantages, such as potential speed increases due to being rendered directly by the browser.

But what animation solution is really best for us to use? In this article, we shall look at how to create animations in jQuery and CSS3, and how they perform against each other.

Introduction to Animation in jQuery

The jQuery library abstracts a lot of complexity away from the developer. As a case in point, here is how to create a simple <div> that is animated after a button is clicked.

		<ol>
  • Include the jQuery library in your page, for example:

    // It's recommended that you use a CDN to use the jQuery library. Here's a link to Google's CDN:
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js?ver=1.8.1"></script>
  • Create the <div> element, and give it some basic style.

    <div></div>
    div {
    	margin-left:10px;
    	margin-bottom:10px;
    	background-color:red;
    	opacity:1;
    	float:left;
    	width:100px;
    	height:1px;
    }
  • Create the button to click that triggers a function to animate the <div>

    <button id="start">Start Animation</button>
  • Write some jQuery code to select the <div> element and apply the effects once the button is clicked. On click, the <div>'s height is increased to 25px and opacity is decreased from 1 to 0.5 over a period of 2000 milliseconds or 2 seconds.

    $("#start").click(function(){
    	$("div").animate({
    		opacity: 0.5,
    		height:"25px",
    	} , 2000);
    });
  • 		</ol>
    

    It's pretty easy to animate an element with jQuery using very little code, and the best thing about jQuery is that your code will work across older browsers, even as far back as IE6!

    Introduction to Animation in CSS3

    To create an animation in CSS3, you need to specify two different constructs in your CSS. First of all, you need to specify what form the animation will take using the @keyframes at-rule, which looks something like this:

    @keyframes my-animation {
    	0%   {height:0px; opacity:1; }
    	100% {height:25px; opacity:0.5; }
    }

    my-animation is the name your animation will be identified by, and the different lines are different keyframes. In each case, the properties inside the curly braces say what value the animated properties will have at each stage of the animation, and the percentages dictate how far through the animation each stage is — in this particular case our animation is pretty simple, so we are only defining the start and end of the animation. Then, to apply your animation to an element on your page, you need to refer to it using the animation property:

    div {
    	margin-left:10px;
    	margin-bottom:10px;
    	background-color:red;
    	opacity:0.5;
    	float:left;
    	width:100px;
    	height:25px;
    	animation: my-animation 2s;
    }

    This is functionally identical to the jQuery example earlier: the <div> is animated over a period of 2 seconds, with its height increasing to 25px and its opacity decreasing from 1 to 0.5. Sounds pretty simple, huh? Unfortunately browser support is not as good for CSS3 animations — IE versions below 10 don't support it, and although all other major browsers support animations well, and the animation spec is now stable, most of them haven't dropped their vendor prefixes yet, so to ensure support just for the moment you'll have to include prefixed versions of the two blocks, for -webkit-, -moz-, -ms- and -o-. The Opera blocks would look like this, for example:

    @-o-keyframes my-animation {
    	0%   {height:0px; opacity:1; }
    	100% {height:25px; opacity:0.5; }
    }

    and

    div {
    		...
    	-o-animation: my-animation 2s;
    }

    This instantly makes the code base a lot more daunting, although if you wanted to reduce the code back to one block, you could use a solution like a preprocessor. Here are a couple of solutions that you could use to add the right prefix at runtime, or during a site build process:

    		<ol>
    
  • SASS — A CSS preprocessor that allows you to include variables, functions, and other features, meaning faster more efficient CSS in some cases. Using SASS shouldn't affect the performance of your site.
  • Prefixfree — A JavaScript library that simple adds the right prefixes to your CSS for the browser accessing it, at runtime. This does mean executing more JavaScript on the client machine, which could lead to a slight performance hit, but this should be relatively minor. The downside is that the layout of the webpage will be broken if the user has JavaScript disabled.
  • 		</ol>
    

    So at the moment, it looks like jQuery is the best way to go, especially in terms of browser support. If you want your site to still be usable in older browsers that don't support the animation, it is advisable to make the default settings of the properties that are animated equal to the end state of the animation, for example above you can see that height is set to 25px and opacity is set to 0.5, so if the animation isn't available, the element just defaults at its end state. This may be acceptable for your site, or it may not — it really depends on what you are trying to do, and what your client or boss is happy with.

    Note: for a lot more detail on CSS animations, read Making a move with CSS3 animations by Chris Mills.

    Animation Wars: CSS3 vs jQuery

    To test the performance of CSS3 animations against jQuery animations, let's set up a test. We will use the code we have already shown above, but in each case we will animate 300 <div>s simultaneously, so that it is easier to actually measure the time taken for the animation to run.

    		<h3>CSS3 Animations</h3>
    

    The execution graph for the CSS3 animation test looks like Figure 1, which also links through to a larger version of the image for clarity. This graph was created using the Opera Dragonfly profiler tool, and the browser used was Opera 12 on Mac OS X.

    Image illustrating the time taken to animate 300 divs with CSS animations in Opera 12

    Figure 1: The time taken to animate 300 <div>s with CSS animations.

    As seen in Figure 1, the entire animation is completed in around 2.9 seconds.

    Next, let's look at memory usage — see Figure 2, which links through to a larger image for clarity. This graph was created using the Memory option inside the Timeline tab of Chrome 21's Developer Tools.

    Image illustrating the heap memory used to animate 300 divs with CSS animations in Chrome 21

    Figure 2: The memory used in animating 300 <div>s with CSS animations.

    The memory used during the CSS3 animation is very small — around 1.5MB, with only about 100 actions required. The final data for this test is:

    • Number of actions performed to finish the animation: 100
    • Time taken to finish executing the animation: 2.9 seconds
    • Memory consumed at the end of the animation: 1.5 MB

    Now let us proceed to see how the jQuery animations fare.

    		<h3>jQuery Animations</h3>
    

    The execution graph for the jQuery animation test looks like Figure 3, which links through to a larger version for clarity. This graph was created using the Opera Dragonfly profiler tool, and the browser used was Opera 12 on Mac OS X.

    Image illustrating the time taken to animate 300 divs with jQuery in Opera 12

    Figure 3: The time taken to animate 300 <div>s with jQuery.

    The entire operation takes just over 5 seconds — a much longer time right? The actual animation doesn't take much longer, but there is all the extra overhead of the JavaScript being loaded (notice a slight delay between the button being clicked and the animation starting.) Also, the number of actions performed by the browser is more than 2000, enormous compared to just 100 for the same animation done using CSS3. Even without using developer tools, you will notice that once the 'Start Animation' button is clicked, there is a slight delay before the animation starts.

    Now onto memory usage — see Figure 4, which links through to a larger image for clarity. This graph was created using the Memory option inside the Timeline tab of Chrome 21's Developer Tools.

    Image illustrating the heap memory used to animate 300 divs with jQuery in Chrome 21

    Figure 4: The memory used in animating 300 <div>s with jQuery.

    When it comes to memory, this animation is a lot hungrier, using close to 6 MB! The final data for this test is:

    • Number of actions performed to finish the animation: 2119
    • Time taken to finish executing the animation: 5 seconds
    • Memory consumed at the end of the animation: 6 MB

    It is also worth noting that the above animations will give different test results across different browsers on different computers, but at least they provide a usable comparison. Currently, Chrome has the fastest JavaScript processor and executes the jQuery animation a few hundred milliseconds faster than its competitors. However it's an entirely different story when it comes to CSS3 animations. Opera 12 blasts ahead giving a smooth animation, as Opera currently leads the way when it comes to DOM manipulation and processing CSS. Firefox 14 and Safari 6 do a very good job at both the areas. The developer's nightmare, IE (the latest stable version being IE 9) doesn't support CSS3 animations but executes jQuery animations decently.

    And the winner is...

    CSS3! Clearly, CSS3 wins the race by lengths. The huge difference in performance is because the browser's CSS processor is written in C++ and native code executes very fast whereas jQuery (JavaScript) is an interpreted language and the browser can't predict JavaScript ahead in time, in terms of what event will occur next.

    Although the results above indicate that you should use CSS3 for animations, you should bear in mind the advantages and disadvantages we discussed earlier on in the article. You need to keep in mind that a fair amount of people still use Internet Explorer 7 and 8, so you should use jQuery if your animations absolutely need to work the same in those older browsers.

    Alternatively, you might be able to live with your animations gracefully degrading in non-supporting browsers, in which case CSS3 animations are the best option.

    Note that for simple animations, such as the trivial one shown in this test example, you could probably use less CSS if you did it as a transition instead of an animation. It really is up to you what to use — transitions are quicker to set up but rely on state changes, whereas animations are arguably more flexible and powerful. Choose what is best for your particular situation.