Using data-* attributes in JavaScript and CSS

When HTML5 got defined one of the things that was planned for was extensibility in terms of data that should be in the HTML, but not visible. The data-* attributes allow us to store extra information on HTML elements without needing to use a non-semantic element or pollute the class name. In essence this is what we did with custom attributes before.

These data attributes can be used in many ways, some are a bad idea but others are a good plan. The rule of thumb is that content that should be visible and accessible should not be stored in them. The reason is that assistive technology is not likely to be able to access them and search crawlers don’t index them either.

The syntax is dead easy. Say you have an article and you want to store some extra information that doesn’t have any visual representation. Just use data attributes for that:


Reading those out in JavaScript is also very simple. You could use getAttribute to read them but the HTML5 standard defines a simpler way: a DOMStringMap you can read out via a dataset property:

var article = document.querySelector('#electriccars'),
              data = article.dataset;

// data.columns -> "3"
// data.indexnumber -> "12314"
// data.parent -> "cars"

Each property is a string (even if you omit the quotes in the HTML) and can be read and written. In the above case setting article.dataset.columns = 5 would change that attribute.

Now, as data-attributes are plain HTML attributes you can even access them from CSS. For example to show the parent data on the article you can use generated content in CSS:

article::before {
  content: attr(data-parent);

You can also use the attribute selectors in CSS to change styles according to the data:

  width: 400px;
  width: 600px;

You can see all this working together in this JSBin example.

Data attributes can also be stored to contain information that is constantly changing, like scores in a game. Using the CSS selectors and JavaScript access here this allows you to build some nifty effects without having to write your own display routines. See the following screencast for an example using generated content and CSS transitions:

The code example shown in the screencast is also on JSBin.

Issues with data-attributes

Sadly enough it seems there is nothing that is so simple and useful that doesn’t come with a price. In this case the main issues to consider are that Internet Explorer does not support the dataset but you’d need to read them out with getAttribute() instead. The other issue is that the performance of reading data-attributes compared to storing this data in a JS data warehouse is bad. Using dataset is even slower than reading the data out with getAttribute().

That said, though, for content that is not to be shown they are a great solution and maybe we can get them into the next IE soon.

About Chris Heilmann

Evangelist for HTML5 and open web. Let's fix this!

More articles by Chris Heilmann…


  1. Maujor

    This article has been translated into Brazilian-Portuguese.
    Translation is hosted at: Uso do atributo data-* em JavaScript e CSS.
    Thanks Chris!

    Editor’s note: Fixed the link

    October 11th, 2012 at 06:46

    1. Robert Nyman

      Great, thank you!

      October 11th, 2012 at 09:16

  2. leoman730

    That’s true. I am waiting for the prime time to using it in production. Thanks for the article.

    October 11th, 2012 at 06:59

    1. Robert Nyman

      Sounds good!

      October 11th, 2012 at 09:17

  3. Rafael

    Learning until my death day.

    I already knew that in JS. As I’m using JQuery almost all the time, always did like that:
    var xpto = $(this).data(‘xpto’);

    But I didn’t know that I could use data attributes in CSS3.
    Thanks a lot, good job :)

    October 12th, 2012 at 08:29

    1. Robert Nyman

      Glad to hear!

      October 12th, 2012 at 12:29

  4. Arthur

    Hi :)

    “That’s true. I am waiting for the prime time to using it in production. Thanks for the article.”

    I am using in production there — It’s also works in IE8, but has issues not only with dataset, but with that what IE does not repaint when data-* property is changed, so, I used hack to force repaint in IE.

    October 12th, 2012 at 14:00

    1. Robert Nyman

      Nice, thanks for the tip!

      October 14th, 2012 at 05:13

  5. fbender

    Why is dataset so slow? Why is it even slower than get/setAttribute? It got its own API, it should be faster or at least as fast as get/setAttribute. The way it is currently implemented will not make anybody use the special API …

    On a related note: Is web content something Snappy is concerned about?

    October 16th, 2012 at 06:34

    1. fbender

      See Bug 802157 (

      October 16th, 2012 at 11:29

  6. Alessandro

    Thanks for the well explained article, really enjoyed it.

    October 17th, 2012 at 03:16

Comments are closed for this article.