jQuery Performance Tips Cheat Sheet

I was hunting for jQuery performance tricks for a while to tune my heavy dynamic web app. After digging in a lot of articles decided to make a list of the best common performance tips. I also built a handy jQuery Performance Cheat Sheet that can be printed or placed on my desktop.

Selectors performance tips:

1. Always Descend From an #id

This is the golden rule of the jQuery selectors. The fastest way to select an element in jQuery is by ID:

$('#content').hide();

or select multiple elements descending from an ID:

$('#content p').hide();
2. Use Tags Before Classes

The second fastest selector in jQuery is the Tag selector ($(‘head’)) because it maps to a native JavaScript method, getElementsByTagName(). The best way is to prefix a class with a tag name (and descend from an ID):

var receiveNewsletter = $('#nslForm input.on');

The class selector is among the slowest selectors in jQuery; in IE it loops through the entire DOM. Avoid using it whenever possible. Never prefix an ID with a tag name. For example, this is slow because it will loop through all <div> elements looking for the ‘content’ ID:

var content = $('div#content'); // VERY SLOW, AVOID THIS

Also, DON’T descend from multiple IDs:

var traffic_light = $('#content #traffic_light'); // VERY SLOW, AVOID THIS
3. Use Sub-queries

Cache the parent object then run queries on it:

var header = $('#header');

var menu = header.find('.menu');
// or
var menu = $('.menu', header);

See live example →

4. Optimize selectors for Sizzle’s ‘right to left’ model

As of version 1.3, jQuery has been using the Sizzle Javascript Selector Library which works a bit differently from the selector engine used in the past. Namely it uses a ‘right to left’ model rather than a ‘left to right’. Make sure that your right-most selector is really specific and any selectors on the left are more broad:

var linkContacts = $('.contact-links div.side-wrapper');

instead of:

var linkContacts = $('a.contact-links .side-wrapper');
5. Use find() rather than context

Indeed, the .find() function seems to be faster. But this counts more when you have a lot of traversing a page with lots of DOM elements:

var divs = $('.testdiv', '#pageBody'); // 2353 on Firebug 3.6
var divs = $('#pageBody').find('.testdiv'); // 2324 on Firebug 3.6 - The best time
var divs = $('#pageBody .testdiv'); // 2469 on Firebug 3.6
6. Harness the Power of Chaining

It’s better to chain the jQuery methods than to cache the selectors:

$('li.menu-item').click(function () {alert('test click');})
                     .css('display', 'block')
                     .css('color', 'red')
                     fadeTo(2, 0.7);
7. Write your own selectors

If you have selectors that you use often in your script – extend jQuery object $.expr[':'] and write your own selector. In the next example I create a selector abovethefold that returns a set of elements that are not visible:

$.extend($.expr[':'], {
	abovethefold: function(el) {
		return $(el).offset().top < $(window).scrollTop() + $(window).height();
	}
});
var nonVisibleElements = $('div:abovethefold'); // Select the elements

DOM manipulation performance tips:

8. Cache jQuery Objects

Cache elements that you query often:

var header = $('#header');
var divs = header.find('div');
var forms = header.find('form');
9. Wrap everything in a single element when doing any kind of DOM insertion

DOM manipulation is very slow. Try to modify your HTML structure as little as possible.

var menu = '<ul id="menu">';
for (var i = 1; i < 100; i++) {
    menu += '<li>' + i + '</li>';
}
menu += '</ul>';
$('#header').prepend(menu);

// Instead of doing:

$('#header').prepend('<ul id="menu"></ul>');
for (var i = 1; i < 100; i++) {
    $('#menu').append('<li>' + i + '</li>');
}
10. Use object detection even if jQuery doesn’t throw an error

It’s great that jQuery methods don’t throw a ton of errors at your users, but that doesn’t mean that as a developer you should just rely on that. Even though it won’t throw an error, jQuery will have to execute a number of useless functions before determining that an object doesn’t exist. So use a quick object detection before calling any methods on a jQuery object that may or may not exist.

11. Use direct functions rather than their convenience counterparts

For better performance you can use direct functions like $.ajax() rather than $.get(), $.getJSON(), $.post() because the last ones are shortcuts that call the $.ajax() function.

12. Store jQuery results for later

Usually you have a general javascript application object – App. Keep your often used jQuery selects in it for later:

App.hiddenDivs = $('div.hidden');
// later in your application:
App.hiddenDivs.find('span');
13. Use jQuery’s internal data() method to store state

Don’t forget about using .data() function to store stuff for your elements:

$('#head').data('name', 'value');
// later in your application:
$('#head').data('name');
14. Use jQuery’s utility functions

Don’t forget about jQuery Utilities functions that can be very handy. My favorites are $.isFunction(), $.isArray() and $.each().

15. Add a JS class to your HTML attribute

Firstly, as soon as jQuery has loaded you use it to add a “JS” class to your HTML tag.

$('HTML').addClass('JS');

Because that only happens when javascript is enabled, you can use it to add CSS styles which only work if the user has JavaScript switched on, like this…

/* In your css */
.JS #myDiv{display:none;}

So, what this means is that we can hide content when JavaScript is switched on and then use jQuery to show it when necessary (e.g. by collapsing some panels and expanding them when the user clicks on them), while those with JavaScript off (and search engine spiders) see all of the content, as it’s not hidden. I’ll be using this one a lot in the future.

Read more on this →

Events performance tips:

16. Defer to $(window).load

Sometimes it’s faster to use $(window).load() than $(document).ready() because the last one occurs before all the DOM elements are downloaded. You should test this before you use it.

17. Leverage Event Delegation (a.k.a. Bubbling)

When you have a lot of elements in a container and you want to assign an event to all of them – use delegation to handle it. Delegation provides you with the ability to bind only one event to a parent element and then check on what child the event acted (target). It’s very handy when you have a big table with a lot of data and you want to set events to the TDs. Grab the table, set the delegation event for all the TDs:

$("table").delegate("td", "hover", function(){
	$(this).toggleClass("hover");
});

Read more →

18. Shorthand for the ready event

If you want to save some bits on compressing your js plugin – replace the $(document).onready() event:

// Instead of:
$(document).ready(function (){
    // your code
});

// you can do:

$(function (){
    // your code
});

Testing jQuery:

19. jQuery Unit Testing

The best way to test a Javascript code is the human way :) But, you still can use some automated tools like Selenium, Funcunit, QUnit and QMock to test your code (especially plugins). I will discuss this in another post because there’s a lot to say about it.

20. Benchmark Your jQuery Code

Always benchmark your code and see which query is slower to replace it. You can achieve this with the Firebug console. Also you can use some of my jQuery shortcut functions to make your testing easier:

// Shortcut to log data to the Firebug console
$.l($('div'));

// Get the UNIX timestamp
$.time();

// Log the execution time of a JS block to Firebug
$.lt();
$('div');
$.lt();

// Run a block of code in a for loop to test the execution time
$.bm("var divs = $('.testdiv', '#pageBody');"); // 2353 on Firebug 3.6

General jQuery performance tips:

21. Use latest version of jQuery

The newest version is usually the best one. Also don’t forget to test your code after changing your jQuery core version. Sometimes it’s not fully backward compatible.

22. Use HTML 5

The new HTML 5 standard comes with a lighter DOM structure in mind. Lighter DOM structure means less elements to traverse for jQuery and better load performance. So, switch to it when possible.

23. Append style tags when styling 15 or more elements

When styling a few elements it is best to simply use jQuery’s css() method, however when styling 15 or more elements it is more efficient to append a style tag to the DOM. This way you get rid of hard coding styles in your scripts.

$('<style type="text/css"> div.class { color: red; } </style>')
.appendTo('head');
24. Don’t load code that isn’t needed

It’s a good technique to break your Javascript code in multiple files and load them only on the pages that need them. This way you don’t load unnecessary JS code and selectors. It’s also easy to manage your code this way.

25. Keep download times to a minimum with one compressed master JS file.

After you decide what javascript files you want to load – compress them and glue in one file. This can be done automatically with open source tools like Minify integrated in your backend code or combining them and minifying with online tools like JSCompressor , YUI Compressor or Dean Edwards JS packer. I prefer the JSCompressor from the online tools.

26. Combine jQuery with raw Javascript where needed

It’s a beauty to work with jQuery but don’t forget that it’s just a framework for Javascript. So you can switch between jQuery code and raw Javascript functions where needed to gain more performance.

27. Load the framework from Google Code

Always load jQuery from Google CDN in your production application – it delivers the script fast from the user’s nearest cache location.
This way you save a server request and also the client has the chance to load the jQuery script instantly from his browser cache if he visited another site that loads the jQuery from Google CDN.

// Link the minified version by specific version
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
28. Lazy load content for speed and SEO benefits

Load chunks of your sites by Ajax to save server side loading time. You can start with the usual sidebar widgets.

Special thanks to Paul Irish, Addy Osmani, Jon Hobbs-Smith and Dave Artz for providing lots of information about jQuery performance.

Thanks to @maxescu who designed this beautiful wallpapers!

What other jQuery performance tips do you suggest?

Please support this wonderful wallpapers and

85 Responses to jQuery Performance Tips Cheat Sheet

  1. Daniel says:

    Excellent and concrete stuff ! Really helpfull !

  2. Gerben says:

    Really nice post. I keep catching myself using class selectors.
    Also, I never knew about the “Always descend from an ID” tip, thanks!

  3. Will Ayers says:

    Awesome read. Going to make sure I put these into all future projects. Just a heads up tho, it looks like there is a code typo on #9 line 10. There is a greater than sign that should be a less than sign.

    $('#header').prepend('>ul id="menu">');

    Should be:

    $('#header').prepend('');

  4. CB says:

    You probably could combine #3, #8 and #12?

    Also, I find #5 a bit surprising, any more results like that you’ve found? Was it just one test case?

    • dumitru says:

      Yes, indeed, 3,8 and 12 advice us to do the same thing – to cache the results.

      As for #5 I found the .find and .ajax so far that are faster than there shortcut methods.

  5. Great stuff! Thank you. 5) was new to me.

    Question about 6): Why is it better to chain than to cache?

    • dumitru says:

      Thanks!

      Well, maybe it’s not better but it’s faster to send the same object result from one function to another then to access it from a variable.

      But I would still recommend caching in variables – it makes the code much more readable and it’s easier to test.

  6. taf2 says:

    not sure the tip, regarding performance with .ajax vs .get/.post is really going to be necessary or noticeable… the round trip time to make a network call is going to be far greater and more noticeable than the overhead of making the extra JS function call. The .ajax is necessary sometimes, but really it means you’ll be writing more code and more code means more transfer time to some degree… meaning what’s faster the JS function call or the time it takes to load your code… Just not sure there is a clear win to using .ajax (more verbose, but sometimes necessary) to the simpler .get/.post

    otherwise, awesome tips and great article. Would have liked to see an explanation to why

    var linkContacts = $(‘.contact-links div.side-wrapper’);
    instead of:
    var linkContacts = $(‘a.contact-links .side-wrapper’);

    would think a.contact-links div.side-wrapper would beat both examples?

    also, were you able to measure any of these in a benchmark?

    • dumitru says:

      Agree, the ajax call performance will do much more overflow than the function you use. But I still use $.ajax that is more explicit and goes really nice with CoffeeScript:

      $.ajax
      url: ‘/’
      method: ‘post’

      As for the selectors, I think that it adds a new parsing level if you add the element name. So, it first searches for all the .side-wrapper than filters all the DIVs elements with this class, then searches for all the .contact-links that include that DIVs and in the end filters out all the A elements. I ran the results are the following (for 10000 runs):

      $(‘.contact-links div.side-wrapper’); 516ms
      $(‘a.contact-links div.side-wrapper’); 546ms

  7. Danny says:

    Nice post.

    Can you elaborate on “object detection”. Are you referring to something like:

    if($(“#foo”).length != 0){
    //jquery magic
    }else{
    return;
    }

    • dumitru says:

      Yes, this is perfect. I also do it in my code:

      $foos = $(‘#foo’);

      if($foos.length){
      $foos.doomTooltip();
      }else{
      return;
      }

  8. Jason Hummel says:

    Regarding inserting multiple elements into the DOM – I personally hate doing all that string concatenation, instead I rely on javascript’s built in documentFragment. DocumentFragment is a lightweight wrapper around a collection of DOM objects. You can create your dF and append all the nodes you need inserted, then insert the entire content of dF into the main DOM all at once.


    var div = document.createElement(“div”);
    div.appendChild( document.createTextNode(“Test div to be inserted 100 times”) );

    var fragment = document.createDocumentFragment();
    for(i = 0; i < 100; i++) {
    fragment.appendChild( div.cloneNode(true) );
    }

    document.getElementById(“container”).appendChild( fragment.cloneNode(true));

    DocumentFragment is fast, and has great browser support going all the way back to IE6.

  9. Graham says:

    Wonderful tips, I can see myself using them often!

    A couple of typos:

    #6: It’s better to chain the jQuery methods than to cache the selectors

    #11: like $.ajax() rather than $.get()

    #20: “which query”

    #24: It’s a good technique to break your

    #27: it delivers the script fast from the user’s nearest cache location. [remove the extraneous "S" at the end of this sentence]

  10. Marcus Tucker says:

    Great article, but it’s rather a shame you’re not using the coding convention that cached jQuery objects should be prefixed with a $ to make them easier to spot in complex code – e.g. var $receiveNewsletter = $(‘#nslForm input.on’);

    Would be great if you would adopt this convention and update all the code examples in your article to reflect it…

  11. N/A says:

    Spelling: brake -> break

  12. Marcus Tucker says:

    Also regarding tip #27 it’s not a good idea to load the script via HTTPS, as it’s slower (it’s encrypted) and only needed if the rest of the page is being delivered HTTPS.

    Fortunately the script can be *automatically* loaded via HTTP or HTTPS depending on the current URL by using the protocol-less URL format //ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js

    See http://stackoverflow.com/questions/4831741/can-i-change-all-my-http-links-to-just for more on this.

  13. Ricardo says:

    1, 2, and 4 are a bit outdated, searching for ID hasn’t been privileged for some time now.

    querySelectorAll, which ends up grabbing 99% of element lookups is almost as fast as getElementById, same goes for getElementsByClassName. Sizzle only servers as fallback for exquisite selectors and normalizing support for IE6/7/8.

  14. Jon Hughes says:

    This is a great list, with the exception of #23 — If you’re going to be styling a lot of elements, you should add it to your stylesheet, and modify the DOM to use those new styles with JS, not add the CSS from javascript itself. I agree that you shouldn’t loop through a bunch of elements to add styles, but let’s not make another evil, even if it is a lesser one.

  15. Keegan Watkins says:

    nice writeup overall, but there are a few points that i think are mis-leading:

    - all your benchmarks are using firebug’s built-in timing functions. this is problematic for several reasons, but the biggest are that firebug uses ‘eval’ under the hood (which is very slow), and it’s just for firefox! in your code, you highlighted that the results were from firebug, but any time you’re arguing benchmarks, its better to make sure your findings are accurate. take a look at jsperf.com if you haven’t already seen it.

    - #14 ‘Use jQuery’s utility functions’
    i use them as well (they are super convenient), but advising people to use ‘$.each’ over a bare-metal ‘for’ or ‘for in’ loop when writing an article about performance is silly. there is no scenario where ‘$.each’ is going to beat a plain loop, as ‘$.each’ uses plain loops under the hood.

    - #16 ‘Defer to $(window).load’
    how can it ‘sometimes be faster to use $(window).load() than $(document).ready()’ ? the dom-ready handler fires either when ‘DOMContentLoaded’ fires (in modern browsers), or as soon as window.doScroll is available (IE). in every test i’ve ever seen, dom-ready fires much faster than the window’s ‘load’ event. dom-ready is always going to fire first, so even if its only a few milliseconds faster than the window’s ‘load’ event, i don’t understand this recommendation.

    • Keegan Watkins says:

      here is a perf test for jQuery.each vs. ‘for’ loops that shows the cost of the callback function overhead.

      here is a perf test for dom-ready vs. window.onload. keep in mind that this isn’t testing which happens first, but which is faster to run. knowing that dom-ready happens first, and that it’s much faster to execute, i don’t get #16.

  16. [...] no more with this guide. Link to this [...]

  17. If you look at the first paragraph of http://24ways.org/2011/your-jquery-now-with-less-suck doing a thing like $(‘#id p’) is not the most performant way of selecting nested tags. It suggests instead of doing $(‘#id’).find(‘p’).

    «the second way can be more than twice as fast as the first»

  18. Steve says:


    Does anyone else leave off the last version point of their scripts, like this?:


    That always retrieves the latest version of jQuery 1.5. I do it, but I’m afraid I lose the caching benefit if no one else does it…

  19. Patrick says:

    Aren’t point 24 and 25 kind of conflicting?

    • dumitru says:

      You can use them both, this way you can have a bunch of glued and compressed scripts that load on demand. :)

      • Patrick says:

        sure. Must get a little tricky to manage after a while though.

        • dumitru says:

          We use the Yii ClientScript class to automatically glue our JS on each page. With each request we add the necessary JS files to the ClientScript stack and Yii generates for us separate bundles of glued scripts where needed.
          I push all this bundles through the Minify tool after they are glued and obtain multiple bundles of glued and minified JS files :)

  20. Adam says:

    Hasn’t .delegate() been superceded by .on()?

  21. vytch says:

    I have read somewhere that DOM manipulation can be made faster if the element we are working on is removed from the DOM.

    var myElement = $(‘#innerDiv’).remove();
    // Doing all the manipulation in #innerDiv…
    then $(“#outerDiv”).append(myElement );

    This saves on the browser redraw.

  22. [...] JQuery Performance Tips Cheat Sheet (dumitruglavan.com) Like this:LikeBe the first to like this post. [...]

  23. Alexgalinier says:

    Hi,

    First of all, great list, i know part of them but it’s helpful to see them gathered.

    But i have a question :
    – 24 : load your the only needed code for each page of a site
    – 25 : compress files to send only one to the user

    We want to do that on, for example, a site with 10 pages and on each pages the scripts that must be loaded are not the sames (some are common but not all). So how to apply your rules in this state ? Should i make 10 compressed Master JS file (one per page) or there is a thing that i’ve not understand :) ? with a bigger site it’s really har to manage.

    Sorry if it’s the same question as Patrick but i’m not sure of your answer.

    • dumitru says:

      It’s my fault, i wasn’t too explicit about it.
      We maintain a big, scalable site that we’ve built about 2 years ago on Yii Framework. So we use the Yii ClientScript class to automatically glue our JS on each page. With each request we add the necessary JS files to the ClientScript stack and Yii generates for us separate bundles of glued scripts where needed.
      I push all this bundles through the Minify tool after they are glued and obtain multiple bundles of glued and minified JS files :)
      It took a while to automate this process but it’s worth it.

  24. Frank says:

    Awesome post, thanks for all the tips.

  25. Marcel Felix says:

    Felicitari pentru tot cea ce faci cu jQuery !!!

    Salutare de la Madrid de la http://www.marcelfelix.com !!!

    Sper sa ai un pic de timp in cazul in care am nevoie de un profesional in JQuery.

    Un cordial saludo

    MF

  26. [...] 原文作者:Dumitru Glavan 编译:伯乐在线 – 唐小娟 [...]

  27. [...] that is clean, efficient, and fast. That applies to jQuery development as well. This cheat sheet by dumitruglavan.com provides you with some tips you can use to improve your jQuery [...]

  28. [...] 原文作者:Dumitru Glavan 编译:伯乐在线 – 唐小娟 [...]

  29. bird says:

    about the 23th tip,why not use the addClass() method ?

  30. [...] Glavan has put together a cheat sheat for us to increase our jQuery efficiency and performance.  Check it out. This entry was posted in Code, Javascript, Jquery by TheCaddy. Bookmark the [...]

  31. [...] cheat-sheet met tips om jQuery performant te [...]

  32. [...] Wallpaper Source 1024×768 | 1440×900 | 1280×960 | 1680×1050 | 1900×1200 [...]

  33. [...] I was hunting for jQuery performance tricks for a while to tune my heavy dynamic web app. After digging in a lot of articles decided to make a list of the best common performance tips. I also built a handy jQuery Performance Cheat Sheet that can be printed or placed on my desktop. jQuery Performance Tips Cheat Sheet | Dumitru Glavan [...]

  34. Aaron Lewis says:

    Thanks for taking the time to write this up! Very sexy stuff. :)

  35. [...] jQuery performance tips Cheatsheet Wallpaper [...]

  36. [...] jQuery performance tips Cheatsheet Wallpaper [...]

  37. [...] jQuery performance tips Cheatsheet Wallpaper [...]

  38. [...] jQuery performance tips Cheatsheet Wallpaper [...]

  39. [...] http://dumitruglavan.com/jquery-performance-tips-cheat-sheet/ Share me:Bookmark on DeliciousDigg this postRecommend on FacebookShare on google plusShare on Linkedinshare via RedditTweet about itSubscribe to the comments on this postTell a friend This entry was posted in Technology and tagged javascript, jquery by Ryan Chambers. Bookmark the permalink. [...]

  40. [...] Paul Irish - Paul Irish’i biliyorsunuz zaten15 Powerful jQuery Tips and Tricks for DevelopersjQuery Performance Tips Cheat SheetJQuery Performance Tips And Tricks With Addy Osmani – VideoYukarıdaki kaynaklara göre bu [...]

  41. [...] jQuery performance tips Cheatsheet Wallpaper [...]

  42. Loren says:

    Thanks for the cheat sheet!

    One question – are there any drawback to designating cached jQuery variables
    with a “$” – I noticed in Douglas Crockford’s Code Conventions page, he recommends never using the dollar sign in a variable name. – http://javascript.crockford.com/code.html

    I have been using “_$varname” to designate private variables – I would assume the browser sees the dollar sign as just another character. Any thoughts on this and why he would recommend not using “$” ?

  43. [...] is fastest in jQuery: searching by id or searching by tag name, I got curious and I found this jQuery Performance Tips Cheat Sheet. Looks like searching by id is the [...]

  44. Japo Domingo says:

    Great post! Hopefully you can update some items such as on() for delegate(). :D

  45. sahil kaundal says:

    useful article.

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>

Switch to our mobile site