Photo of Nathan Shubert-Harbison Nathan Shubert-Harbison

Main content

Using the HTML5 custom data-* attribute

There are a lot of exciting new features in HTML 5. Video, audio, and canvas seem to be the most discussed around the watercooler, but the data-* attribute—though seemingly less earth shattering—is extremely useful.

data-* what?!

The data-* attribute is a way to store custom metadata about an element within its own markup. In the past we might have done this with a class or the rel attribute, but data-* gives us an attribute specifically for this purpose.

The fun thing about data-* attributes—and part of the reason they’re so flexible—is that you can name them as needed. For example, if you were making a coffee app with a list of coffee roasts, and wanted to store single origin information in a list item, you could create a data-* attribute called data-single_origin.

<ul>
    <li data-single_origin="true">Hyper roast</li>
</ul>

Since we create the name of the data attribute as needed, we can create as many as we need. If we also wanted to store the country of origin, we could create a data-country_origin attribute.

<ul>
    <li data-single_origin="true" data-country_origin="Belize">Hyper roast</li>
</ul>

We could continue with data-* attributes for shade grown, fair trade, or any other types of information we wanted to store.

Once we have all of our metadata neatly stored in data-* attributes, we can do all sorts of fun things with it, like sort items with JavaScript.

The only limitations according to the spec are that data-* attributes be spelled without uppercase ASCII letters, that data is used by its own applications (as opposed to being scraped by other apps), and that the names be XML compatible. As the use of data-* attributes grows, it might also be advisable to namespace your attributes to prevent conflicts later on. For example, say our coffee app was called roastr (it is web “can I buy a vowel”, 2.0 after all), we could have an attribute named data-roastr-shade_grown.

data-* vs. classes

You might be asking why use data-* attributes at all, and that would be a fair question. We could achieve a similar result using class names. With our coffee example, we could store all of that metadata using class names, and use that for any type of sorting or other functionality. The previous example with classes could look like this:

<ul>
    <li class="single_origin country_origin-belize">Hyper roast</li>
</ul>

Taking that approach would work, and it’s the approach we’ve taken for years. However, data-* attributes offer a much cleaner way to store metadata for a few reasons:

  • Using data-* attributes separates metadata from classes used for styling. Classes like first and last are useful in CSS, but separating them from metadata provides better clarity, and enables more obvious functionality.
  • Similar to not putting all of our classes and metadata in a single heap, we can separate our pieces of metadata from each other.
  • It’s far easier to parse metadata from data-* because, aside from knowing that our attribute contains the info we want, we wouldn’t have to remove parts of the string to retain the data. In the above example using classes, we wouldn’t have to remove country_origin- to retrieve belize.

Retrieving data attribute values with JavaScript

We’re attaching metadata to our elements because we want use that data later on, likely with JavaScript. Fortunately, this is really easy to do.

<ul>
    <li id="coffee-12" data-single_origin="true">Hyper roast</li>
</ul>
var coffee12 = document.getElementById('coffe-12');
var isSingleOrigin = coffee12.getAttribute('data-single_origin');

We can set an attribute too:

coffee12.setAttribute('data-country_origin', 'Mexico');

This is even easier with jQuery, using the .data() method:

var coffee12IsSingleOrigin = $("#coffee-12").data("single_origin");

And to set a value:

$("#coffee-12").data("country_origin", "Mexico");

Note that we omitted the data- prefix when using jQuery’s .data() method.

We can also use the .attr() method.

var coffee12IsSingleOrigin = $("#coffee-12").attr("data-single_origin");

Say we had a bunch of li elements with a class of roast, each with a boolean value stored in data-single_origin, and we only want to do something to the items that have a true value. We could easily do that using jQuery’s .data() method.

$('.roast').each(function(){
if ( $(this).data('single_origin') == true ) {
console.log("Single origin beans, ftw");
}
});

Note that dynamic typing occurred, turning our string "true" into a true boolean.

Dataset

The HTML5 spec also includes a dataset property in the JavaScript API. Support isn’t as broad as using getAttribute, but we could retrieve a value like so using dataset:

var isSingleOrigin = coffee12.dataset.single_origin;

And there you have it! Not as flashy as canvas, but an incredibly useful tool you’ll find plenty of uses for.

More information on data-* attributes:

This post was originally written for the Domain7 blog.