Working with HTML5 data attributes

A drawing of a cartoon man pointing upwards

Heads up! This post was written in 2014, so it may contain information that is no longer accurate. I keep posts like this around for historical purposes and to prevent link rot, so please keep this in mind as you're reading.

— Cory

Before HTML5, working with arbitrary data sucked. To keep things valid, you had to stuff things into rel or class attributes. Some developers even created their own custom attributes. Boy, was it a mess.

But that all changed with the introduction of HTML5 custom data attributes. Now you can store arbitrary data in an easy, standards-compliant way.

How do data attributes work? #

A data attribute is exactly that: a custom attribute that stores data. They are always prefixed with data- followed by something descriptive (according to the spec, only lower case letters and hyphens are allowed). An element can have any number of data attributes you want.

Here's an example using a list item to store data for a user:

<li data-id="1234" data-email="calvin@example.com" data-age="21">Calvin</li>

Of course, this data isn't very useful to a visitor because they can't actually see it, but it's wildly useful for building web applications. Imagine a delete button in your app:

<button type="button" data-cmd="delete" data-id="1234">Delete</button>

All the data you need is right there to send to your backend script. No more rel stuffing or parsing IDs and actions out of other attributes. Data URLs make your life easier.

What can you store? #

One thing to remember when working with data attributes is that you can't store objects in them. Well, you can if you serialize them, but we'll save that for another post.

For now, just know that you're pretty much limited to storing strings.

Reading/writing data attributes with JavaScript #

Using the delete button as an example, let's look at how we can access this data with JavaScript.

// Here's our button
var button = document.getElementById('your-button-id');

// Get the values
var cmd = button.getAttribute('data-cmd');
var id = button.getAttribute('data-id');

// Change the values
button.setAttribute('data-cmd', yourNewCmd);
button.setAttribute('data-id', yourNewId);

Pretty simple, right? Now you can pass cmd and id to your app in an AJAX request or do whatever else you need to do with it.

Reading/writing data attributes with jQuery #

Here's the same thing using jQuery's .attr() method:

// Get the values
var cmd = $('#your-button-id').attr('data-cmd');
var id = $('#your-button-id').attr('data-id');

// Change the values
$('#your-button-id')
    .attr('data-cmd', yourNewCmd)
    .attr('data-id', yourNewId);

Don't get this confused with jQuery's .data() method. Although there is some overlap in how data attributes and .data() work, they're two totally different things. If you're not familiar with it, just stick with .attr().

Using the dataset API #

HTML5 actually has an API just for working with this type of data. Alas, IE10 and below don't fully support it, but it's still worth mentioning.

Using the button example again, here's how to get and set data attributes using the dataset API:

// Here's our button
var button = document.getElementById('your-button-id');

// Get the values
var cmd = button.dataset.cmd;
var id = button.dataset.id;

// Change the values
button.dataset.cmd = yourNewCmd;
button.dataset.id = yourNewId;

Note how there's no data prefix or dashes here. Similar to the way CSS properties work in JavaScript, you'll need to use camel case notation. The dataset API converts each one so you'll always have data-some-attribute-name in your HTML and dataset.someAttributeName in your JavaScript. Magic!

Things you can do with data attributes #

The examples above are very basic, but you can do so much with custom data attributes. Here are a few examples off the top of my head.

Filtering #

Say you have a list of things and you want to filter them by keyword. Just put the keywords into a data attribute and write a short script to loop through and show/hide them accordingly.

<input type="text" id="filter">

<ul class="cars">
    <li data-models="mustang, f150, 500, fusion">Ford</li>
    <li data-models="corvette, silverado, impala, cavalier">Chevrolet</li>
    ...
</ul>

Here's a quick and dirty filter using jQuery:

$('#filter').on('keyup', function() {
  var keyword = $(this).val().toLowerCase();
  $('.cars > li').each(function() {
    $(this).toggle(keyword.length < 1 || $(this).attr('data-models').indexOf(keyword) > -1);
  });
});

Styling #

It's arguably better to use classes, but you can style things against data attributes too. Here's how to apply a style if the element has a certain data attribute (regardless of its value). First, the HTML:

<span class="label" data-warning>

Now the CSS:

[data-warning] {
  background: red;
}

But what if we wanted to style it based on the data attribute's value? This will work for any data-warning attribute that contains the word error:

[data-warning*=error] {
    color: red;
}

Configuring #

Bootstrap uses data attributes as an HTML alternative to configuring plugins via JavaScript. Here's an example of a popover:

<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="top" data-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">
  Popover on top
</button>

A better way to store data #

Custom data attributes are widely used all over the web. The nice thing is that they work fine in older browsers, and they adhere to web standards moving forward. That means you can start using them today knowing that they won't stop working tomorrow.

I've shown you a few common ways to use custom data attributes. What other uses can you think of? Have you used them before? Let me know by commenting below!