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!