Managing Custom Data with the HTML5 Dataset API

Share this article

For a long time now, web developers have needed to store data on DOM elements. One of the most common methods was to add data as class names. Purists, like me, always felt wrong doing this, because that is not the place for data. An alternative way was to add custom attributes to the elements of interest. This practice lead to invalid markup because custom attributes were not supported by the specification. So, you ended up sacrificing validation in order to achieve your goal. This situation was very frustrating. Fortunately, HTML5 fixed it. In fact, HTML5 not only introduced the possibility of adding custom attributes via data attributes, but also exposed an API, called the dataset API, to work with them. In this article, we’ll discover how this API works and what it can do for us.

What is the Dataset API?

Among all the new elements (such as article, section, header, and footer) and the new APIs (such as High Resolution Time, User Timing, getUserMedia, and Page Visility), HTML5 also introduced data attributes and the dataset API. Before delving into our discussion of the dataset API, I want to give you a quick refresher of what are data attributes. Data attributes get their name from the data- prefix. This also explains why sometimes they are referred as data-* attributes. An example of an element using data attributes is shown below.
<span id="element" data-level="1" data-points="100" data-opponent="Dragon"></span>
The names you can choose aren’t limited to a single word. Names can also consist of multiple words, separated by hyphens (-). So, let’s say that you want to change the opponent attribute to final opponent. You would write the element as shown in the following example.
<span id="element" data-level="1" data-points="100" data-final-opponent="Dragon"></span>
You should now have a clear idea of what data attributes are, so let’s start discussing the API. The dataset API gives us a simple way of dealing with data attributes. This API allows us to set, get, or even delete data attribute values. The dataset API exposes a DOM element attribute named dataset, which contains a DOMStringMap
object. This object’s keys are the names of the data attributes without the data- prefix. The corresponding values are those of data attributes. If the name of an attribute is made of multiple words separated by a hyphen, it’s converted to camelCase. Let’s look at the following example:
var obj = document.getElementById("element").dataset
The previous statement will the following object in the variable obj.
{
  level: "1",
  points: "100",
  finalOpponent: "Dragon"
}
Individual data attributes can be accessed using the setAttribute(), getAttribute(), and removeAttribute() methods. However, the dataset API gives you a convenient and direct way to access custom data. If the API is not supported, you should retrieve all the attributes and then filter those not starting with data-. And, while the dataset API is simpler, it is also slower than the previously mentioned methods, as proven by this JSperf. However, unless you’re accessing thousands of attributes per second, you won’t notice any difference. Now that we’ve discussed the dataset API, it’s time to see how we can use it.

Setting Values

Imagine we want to add the attribute data-media to our element, and set its value to song. To perform this task, we can write the following code. Note that if the attribute was already defined, its value is overwritten.
document.getElementById("element").dataset.media = "song";

Getting Values

Creating attributes is completely useless if we can’t retrieve them. Let’s say that we want to print the value of the data-final-opponent attribute to the console. The code to do so would like like this:
console.log(document.getElementById("element").dataset.finalOpponent);
// prints "Dragon"

Deleting Attributes

To delete a value, simply overwrite it using the empty string. However, to actually delete an attribute we can use the JavaScript delete
operator. An example which deletes the data-final-opponent attribute is shown below.
delete document.getElementById("element").dataset.finalOpponent;
After executing the previous statement, attempting to retrieve the attribute’s value will yield undefined.

Browser Compatibility

The dataset API is widely supported among desktop and mobile browsers, aside from Internet Explorer which only implements the API in IE11. In addition, there are some older mobile browsers that don’t support it, but generally speaking the support is excellent. For those browser that don’t support this API, a polyfill named HTML 5 dataset Support is available. If you don’t want to add a polyfill for such a simple API, you can use setAttribute(), getAttribute(), and removeAttribute() (as previously mentioned).

Demo

Learning something new is great, but it’s even better if we can play with it. So, we’ll build a small demo that will allow us to see how the dataset API works. The general idea is to have an element on which we can get, set and delete data attributes. To see what’s going on and to keep an eye on the current state of the element, we’ll have a small window where we’ll log the changes we made. In addition, we’ll have an area showing the raw HTML code of the element representing its current state. In order to play with its data attributes, we need two input boxes: key and value. The former allows us to set the name of attribute we want to store, while the latter is where we’ll write the value of the attribute. Because we want to allow for three different actions (get, set, and delete), we’ll also need three buttons to which we’ll add handlers. As always, we’ll also test for browser support, and if the test fails, we’ll show the message “API not supported.” Before showing you the demo code, there are two considerations I want to share with you. The demo assumes that you’ve read the whole article. Therefore, you’re aware that to perform an action on a data attribute named with more than one word, you have to convert the name to camelCase. If you want to change this behavior and be able to write “final-opponent” instead of “finalOpponent”, I’ve written two utility functions just for you. To use these functions, you need to add them to the demo and change the code so that you call them inside the handlers before performing the action. The source code of these functions is listed below.
function hyphenToCamelCase(string) {
  return string.replace(/-([a-z])/g, function(string) {
    return string[1].toUpperCase();
  });
}

function camelCaseToHyphen(string) {
  return string.replace(/([A-Z])/g, function(string) {
    return '-' + string.toLowerCase();
  });
}
The second thing to keep in mind is that so far we have accessed the data attributes using the dot operator because we knew its name ahead of time. In the demo we don’t have this information, so to access the properties of the dataset, we’ll use the equivalent square bracket notation. Now, it’s time to show you the source code. As usual, a live demo of the code is available here.
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
    <title>Dataset API Demo</title>
    <style>
      body
      {
        max-width: 500px;
        margin: 2em auto;
        font-size: 20px;
      }

      h1
      {
        text-align: center;
      }

      .hidden
      {
        display: none;
      }

      #log
      {
        height: 200px;
        width: 100%;
        overflow-y: scroll;
        border: 1px solid #333333;
        line-height: 1.3em;
      }

      .buttons-demo-wrapper
      {
        text-align: center;
      }

      .button-demo
      {
        padding: 0.5em;
        margin: 1em;
      }

      .author
      {
        display: block;
        margin-top: 1em;
      }
    </style>
  </head>
  <body>
    <h1>Dataset API</h1>

    <h3>Live sample element</h3>
    <div id="showcase">
      &lt;span id="play-element" class="hidden" data-level="1" data-points="100" data-final-opponent="Dragon"&gt;&lt;/span&gt;
    </div>

    <h3>Play area</h3>
    <div>
      <label for="key">Key:</label>
      <input type="text" id="key"></input>
      <label for="value">Value:</label>
      <input type="text" id="value"></input>

      <div class="buttons-demo-wrapper">
        <button id="set-data" class="button-demo">Set data</button>
        <button id="get-data" class="button-demo">Get data</button>
        <button id="delete-data" class="button-demo">Delete data</button>
      </div>
    </div>

    <span id="d-unsupported" class="hidden">API not supported</span>

    <h3>Log</h3>
    <div id="log"></div>
    <button id="clear-log" class="button-demo">Clear log</button>

    <span id="play-element" class="hidden" data-level="1" data-points="100" data-final-opponent="Dragon"></span>

    <script>
      if (!"dataset" in document.createElement("span")) {
        document.getElementById("d-unsupported").classList.remove("hidden");
        ["set-data", "get-data", "delete-data"].forEach(function(elementId, index) {
          document.getElementById(elementId).setAttribute("disabled", "disabled");
        });
      } else {
        var playElement = document.getElementById("play-element");
        var key = document.getElementById("key");
        var value = document.getElementById("value");
        var log = document.getElementById("log");
        var showcase = document.getElementById("showcase");

        document.getElementById("clear-log").addEventListener("click", function() {
          log.innerHTML = "";
        });
        document.getElementById("set-data").addEventListener("click", function() {
          if (key.value.indexOf("-") !== -1) {
            log.innerHTML = "Warning! Hyphen not allowed. Use camelCase instead.\n" + log.innerHTML;
          } else {
            playElement.dataset[key.value] = value.value;
            showcase.textContent = playElement.outerHTML;
            log.innerHTML = "Set data-" + key.value + " attribute to '" + value.value + "'<br />" + log.innerHTML;
          }
        });
        document.getElementById("get-data").addEventListener("click", function() {
          if (key.value.indexOf("-") !== -1) {
            log.innerHTML = "Warning! Hyphen not allowed. Use camelCase instead.<br />" + log.innerHTML;
          } else {
            log.innerHTML = "Get data-" + key.value + " attribute. Value: '" + playElement.dataset[key.value] + "'<br />" + log.innerHTML;
          }
        });
        document.getElementById("delete-data").addEventListener("click", function() {
          if (key.value.indexOf("-") !== -1) {
            log.innerHTML = "Warning! Hyphen not allowed. Use camelCase instead.<br />" + log.innerHTML;
          } else {
            delete playElement.dataset[key.value];
            showcase.textContent = playElement.outerHTML;
            log.innerHTML = "Deleted data-" + key.value + " attribute<br />" + log.innerHTML;
          }
        });
      }
    </script>
  </body>
</html>

Conclusions

In this article, we’ve discussed the dataset API and how it can help us to store custom attributes on DOM elements. As we’ve seen, the API is very easy to use. In addition, it’s also widely supported among desktop and mobile browsers. You can start using it right away in your next project. In case you have any doubts, I encourage you to play with the provided demo or post a question.

Frequently Asked Questions about Managing Custom Data with HTML5 Dataset API

What is the HTML5 Dataset API and how does it work?

The HTML5 Dataset API is a set of tools that allows developers to store custom data directly within HTML elements. This is achieved through the use of data attributes, which are custom attributes that start with the word ‘data-‘ followed by a custom name. These attributes can be accessed and manipulated using JavaScript, providing a convenient way to store and retrieve data directly from the HTML.

How can I access data attributes using JavaScript?

You can access data attributes in JavaScript using the dataset property. This property provides a DOMStringMap object for the element’s data attributes. For example, if you have an element with a data attribute like data-example=”value”, you can access it in JavaScript like this: element.dataset.example.

How can I convert data attributes to an object?

Converting data attributes to an object can be done using JavaScript. You can iterate over the dataset property of the element and assign each attribute to a property of the object. Here’s an example:

let obj = {};
for (let key in element.dataset) {
obj[key] = element.dataset[key];
}

Can I use the HTML5 Dataset API in all browsers?

The HTML5 Dataset API is widely supported in all modern browsers, including Chrome, Firefox, Safari, and Edge. However, it is not supported in Internet Explorer 10 or earlier. You can check the current level of support on websites like Can I Use.

What is a DOMStringMap?

A DOMStringMap is an object provided by the HTML5 Dataset API. It represents a collection of data attributes of an HTML element. Each data attribute is represented as a property of the DOMStringMap object, with the property name being the attribute name minus the ‘data-‘ prefix and the property value being the attribute value.

Can I modify data attributes using JavaScript?

Yes, you can modify data attributes using JavaScript. You can do this by assigning a new value to the corresponding property of the dataset object. For example, if you have an element with a data attribute like data-example=”value”, you can modify it in JavaScript like this: element.dataset.example = “new value”.

Can I add new data attributes using JavaScript?

Yes, you can add new data attributes using JavaScript. You can do this by adding a new property to the dataset object. For example, you can add a new data attribute like this: element.dataset.newAttribute = “value”.

Can I remove data attributes using JavaScript?

Yes, you can remove data attributes using JavaScript. You can do this by using the delete operator on the corresponding property of the dataset object. For example, you can remove a data attribute like this: delete element.dataset.example.

Can I use data attributes in CSS?

Yes, you can use data attributes in CSS. You can use them in attribute selectors to style elements based on their data attribute values. For example, you can style an element with a specific data attribute value like this: [data-example=”value”] { color: red; }.

What are some use cases for the HTML5 Dataset API?

The HTML5 Dataset API can be used in a variety of situations where you need to store custom data in HTML elements. This can be useful for things like storing state information for interactive elements, storing configuration options for scripts, or storing metadata for elements.

Aurelio De RosaAurelio De Rosa
View Author

I'm a (full-stack) web and app developer with more than 5 years' experience programming for the web using HTML, CSS, Sass, JavaScript, and PHP. I'm an expert of JavaScript and HTML5 APIs but my interests include web security, accessibility, performance, and SEO. I'm also a regular writer for several networks, speaker, and author of the books jQuery in Action, third edition and Instant jQuery Selectors.

dataset
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week