HTML 5 data-* attributes, how to use them and why

It is always tempting to add custom attributes in HTML so that you can use the data stored there to do X. But if you do that there is no way of knowing if your HTML attribute will not be overridden in the future and used for something else and additionally you will not be writing valid HTML markup that can pass HTML 5 validator and with that you can create some very bad side effects. That is why there is a spec in HTML 5 called custom data attributes that enables number of useful features.
You may go around and read the specs but the basic idea is very simple, you can add any attribute that starts with "data-" and that attribute will be threated as non-visible data for that attribute. By non-visible I mean that it is not something that gets rendered to the client so it does not affect the layout or style of the page but it is there in the HTML so in no way this is private.
So let's get right into it, the following snippet is a valid HTML5 markup


  <div id="awesome" 
     data-hash="3e4ae6c4e30e50e4fdfc7bf439a09974">Some awesome data</div>


Great so now how do you read the data from there? Well you can go through the elements and get the attributes you need or you can go and use jQuery if it is already there. Using jQuery's .data() API  you can work with the "data-*" elements. One method is .data(obj) added in jQuery1.4.3 that basically retrieves data for the selected element.
For example if you want to get the value of the data-hash attribute with the following snippet:


 var dataHashValue = jQuery("#awesome").data('hash');
 console.log(dataHashValue);

You can also use json syntax in the data fields  for example if you have the following HTML:

<div id="awesome-json" data-awesome='{"game":"on"}'></div> 

Accessing data from js can be done directly just by adding the json key to the result :

  var gameStatus= jQuery("#awesome-json").data('awesome').game;
  console.log(gameStatus);

You can also set the data using .data(key,value) directly from JS. One important thing to remember is that the "data-*" attributes should be linked to the element in some way. They should add additional info about that element or the data it contains and not act just like a storage for everything 

You can go around and play with it in the following jsfidde.

Related links:

11 comments:

Anonymous said...

Tanks for this

Diego said...

Very nice!

petar said...

congrats on hitting reddit

petar said...
This comment has been removed by the author.
Goran Peoski said...

.data(obj) added in jQuery1.4.3 BASICALLY DOES NOT retrieve data from the selected element, but FOR the selected element.

What .data() basically does is read an internal jQuery hash (accessible by $.cache) and ONLY WHEN IT CAN'T FIND the certain key for the element in question does it look the data-* attributes.

To make sure you get the data ALWAYS USE the .attr() method.

Try playing with this jsfiddle for a bit http://at.azder.mk/LTfluZ .

Mite Mitreski said...

You can only have side effect if you have used the same key for that element to store some data. It basically depends if you need constant data or some initial data for some elements.
data-* are automatically pulled into the jQuery data object and if they are overridden somehow then that should probably be the normal behavior.
But yeah it should be data for the element not from the element

jaspermogg said...

Great post buddy, thanks!

Anonymous said...

Can't stress enough the importance of that last paragraph. Unnecessary DOM lookups are inefficient. If you're doing a .each() that accesses the data and then acts on the node, fine. If you're just using the data, use an array.

This is especially true if you're doing some conditional where you only need to act on DOM elements that meet certain conditions. Scope the cached query, array, and method to a parent object that makes sense. Don't substitute jQuery for sensible programming patterns.

Scott P. said...

The data-for attribute was a great addition to HTML as your post points out. It's a great way to create non-brittle web pages using javascript. I shudder thinking about the way I was storing data on the page about 5-6yrs ago that needed to be accessed via javascript.

Anonymous said...

Just so that people know, the format of any JSON in a data attribute when used via jQuery, as demonstrated here, is..

data-name='{"foo":"bar"}'

..using the following will NOT work..

data-name="{'foo':'bar'}"

..which I appreciate not strictly a properly formatted JSON string but considering the vast majority of us use " as the containing quotes you would think jQuery would compensate for this.

Anyway, I found your post via Google while investigating temporary data storage and was confused as to why my implementation was not correct. I'm only adding in a comment here so if anyone else encountered the same problem they would have an answer.

Mite Mitreski said...

Thanks for your input, you are correct.
This is something I had not mentioned. In the JSON format we MUST use double-quoted strings.
The definition goes as this :

A string is a sequence of zero or more Unicode characters, wrapped in double quotes, using backslash escapes. A character is represented as a single character string. A string is very much like a C or Java string.



More on
http://www.json.org/