Skip to main content Accessibility Feedback

How performant are data attributes as selectors

Whenever I write about using data attributes as selectors, someone asks me how performant it is compared so using classes.

Let’s find out!

How to test performance

The performance.now() method returns a timestamp in milliseconds.

We can use this to measure how long different approaches take by capturing it’s value just before and just after we inject a bunch of DOM elements. By subtracting the two values, we get the elapsed time in milliseconds that it took to complete our tasks.

var start = performance.now();
// Do some stuff...
var end = performance.now();

// The time it took to complete our tasks
console.log('It took ' + (end - start) + 'ms to complete this task');

Setting up a test

To set up my test, I’m going to create an HTML document with ten thousand list items in it. I’ll give each item both a class and data attribute, and use both as selectors.

Creating ten thousand items by hand would take forever, so let’s use JavaScript to do it for us.

I created an empty element with an ID of #app on it. Then, I ran a for loop ten thousand times, creating an element and injecting it into the DOM on each loop.

// Variables
var app = document.querySelector('#app');
var count = 10000;
var elem;

// Create elements
for (var i = 0; i < count; i++) {

	// Create element
	elem = document.createElement('li');
	elem.textContent = 'List Item ' + i;

	// Add ID, class, and data attribute
	elem.id = 'list-item-' + i;
	elem.className = 'list-item';
	elem.setAttribute('data-item', i);

	// Inject into the DOM
	app.appendChild(elem);

}

Running the tests

To run our tests, we’ll cache the value of performance.now(), selector our items by class or data attribute, and then cache the value of performance.now() again.

Then, we’ll subtract the difference between the two to measure how long it took.

/**
 * Start Performance Tests
 */

var start, end;


//
// By Class
//

start = performance.now();
var byClass = document.querySelectorAll('.list-item');
end = performance.now();
console.log('By class took ' + (end - start) + 'ms.');


//
// By Data Attribute
//

start = performance.now();
var byClass = document.querySelectorAll('[data-item]');
end = performance.now();
console.log('By data attribute took ' + (end - start) + 'ms.');

The results

The results varied quite a bit each time I ran the test.

Sometimes classes were faster. Sometimes data attributes were faster. Sometimes both took a long time, and sometimes both ran really quickly.

On average, they both took about half a millisecond to run each. In other words: no difference whatsoever.

Selector Time
Class 0.5ms
Data Attribute 0.5ms

Download the test files from GitHub to run the tests yourself.