Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

Setting multiple CSS properties at once with jQuery doesn't batch

There's a trick that was suggested in a few articles on the internet, that whenever you should modify a lot of CSS properties, you should batch them in one call:

  // instead of this
  $('body').css('backgound-color', '#F00');
  $('body').css('width', 100);
  $('body').css('height', 300);

  // do this
  $('body').css({
    'background-color': '#F00',
    'width': 100,
    'height': 300
  });

By groupping them in one place, we hope that jQuery is smart enough to batch everything into one call.

Turned out, it's not.

If you look at jQuery source code, where the call to jQuery.css starts:

  // https://github.com/jquery/jquery/blob/1b74660f730d34bf728094c33080ff406427f41e/src/css.js#L396
  css: function( name, value ) {
    return access( this, function( elem, name, value ) {
    ...

It will then called the access function to determine if the passed parameter is a single style change or a bulk changes:

  // https://github.com/jquery/jquery/blob/master/src/core/access.js#L10
  var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
    ...
    // Sets many values
    if ( toType( key ) === "object" ) {
      chainable = true;
      for ( i in key ) {                                        // <===
        access( elems, fn, i, key[ i ], true, emptyGet, raw );  // <===
      }

As you can see here, jQuery didn't attempt to batch anything when it received a key-valued object passed into .css() method, and eventually, it change the CSS properties directly via element.style.<property> = value:

  // https://github.com/jquery/jquery/blob/master/src/css.js#L256
  if ( isCustomProp ) {
    style.setProperty( name, value );
  } else {
    style[ name ] = value;
  }

So, what's the point of batching the CSS properties into one .css() call here?

It's the selector, since our initial example is too simple, let me show you another one:

  $('.container h3[data-tag="product-header"]:not(.hidden) a[href]').css('background', '#F00');
  $('.container h3[data-tag="product-header"]:not(.hidden) a[href]').css('width', 500);
  $('.container h3[data-tag="product-header"]:not(.hidden) a[href]').css('height', 30);

Do you see the problem now? Yes, that monsterous query selector! querying a DOM element is costly, so don't do it repeatly, batching them all in to one call will save you the cost of querying.

  $('.container h3[data-tag="product-header"]:not(.hidden) a[href]').css({
    'background-color': '#F00',
    'width': 500,
    'height': 30
  });

At least, we solved some performance issue, althought it's not the one we intended to solve, but better than nothing.

Hail jQuery!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.