HTML 5 isn't exactly new anymore (it debuted in late 2014), but its features aren't as well known as the more venerable areas of HTML. Sometimes this is due to a lack of browser support, sometimes to developers clinging needlessly to jQuery, sometimes to a team trying to maintain a large, cumbersome site that predates HTML 5. For those of us with the freedom to embrace all that HTMl 5 has to offer, there's a lot of power to be had. Data attributes are one of the more powerful additions to arrive in HTML 5.
Data Attributes in HTML
It's quite common to use attributes in our HTML. We might use the class
attribute to apply a CSS class to an element, write into the style
attribute to override, test, or debug the stylesheet, or add a boolean attribute like required
to input
elements in a form. The big distinction between data attributes and attributes on the whole is that data attributes are defined by the developer and not built into HTML from the start. Data attributes are hooks that we can set up to provide new ways for our HTML to communicate with our CSS and our JavaScript.
Creating an HTML Data Attribute
Adding a data attribute is easy. Any HTML element can have any number of data attributes added to its opening tag. We simply type data-
followed by the name of our attribute into the element's opening tag alongside any other attributes we're already using.
For example, let's create a data attribute called "badges" and use it to attach a number to a p
element.
<p data-badges="3">This is a paragraph element.</p>
Data Attributes in CSS
There are two ways we can easily look at our data attributes from our stylesheet. The first is attribute selectors, and the second is the attr()
function.
Using Attribute Selectors in CSS
We can target HTML attributes when we're writing CSS rules. A common use for this is selecting certain types of input elements by writing rules for something like input[type="checkbox"]
. Really any attribute can be a selector in our CSS rules. Using data attributes to apply styles this way can make stylesheet organization better by reducing helper classes; instead of creating arbitrary classes like .one-badge
, .two-badges
, .three-badges
, and attaching them manually to elements, we can target a data attribute to apply the desired styles and cultivate a more semantic stylesheet. Our intentions will be more clear when other people (or our future selves) drop in to read our CSS.
So for example, if we wanted to style our paragraph with the “badges” data attached, we could check that data attribute using square braces [ ]
in our stylesheet.
p[data-badges=“1”] {
background: orange;
}
p[data-badges=“2”] {
background: gold;
}
p[data-badges=“3”] {
background: lime;
}
This makes it more obvious where our logic for changing background
values is coming from than opaquely slapping helper classes on p
elements would.
Using the attr()
Function in CSS
The attr()
function allows us to pull data into our CSS stylesheet from our HTML document. This allows us to move further away from the manual application of styles provided by attribute selectors and closer to treating a data attribute like a variable.
CSS rules are applied to HTML elements that match the selectors enclosing those rules. The attr()
function lets us grab data from the element that we're selecting and styling. To do this, use attr()
and pass it the name of your desired data attribute as an argument.
For example, let's display the value of a data attribute after our paragraph element. We just need to add a CSS rule to our stylesheet.
p::after {
content: attr(data-badges);
}
Data Attributes in JavaScript
JavaScript allows us to complete the transition away from manually attaching data to elements. Data attributes are a great way to endow HTML elements with extra information, but getting and setting the data from these attributes with JavaScript is what really makes this feature useful. Like writing them into HTML and targeting them with CSS, HTML 5 makes working with data attributes in JavaScript very easy.
Reading HTML Data Attributes in JavaScript
All of an HTML element's data attributes are accessible at Element.dataset
. This object dataset
is a DOMStringMap with each data attribute attached as a child. Simply drill down through dataset
and request your attribute by name.
// Start by grabbing our paragraph element
var element = document.querySelector('p');
// Now we can check the value of our data attribute
var badges = element.dataset.badges;
console.log('Badges data attribute value:', badges);
Setting HTML Data Attributes in JavaScript
When we want to set a new value for a data attribute, we can use the same JavaScript function that we'd use for setting any built-in HTML attribute: setAttribute()
.
// We can set our data attribute to 4
element.setAttribute('data-badges', '4');
Notice that here we include data-
before the name of our attribute since this function isn't specific to data attributes.
Support and Accessibility Notes
As always, be sure to check how widely supported features of the web are before you use them in production. HTML data attributes enjoy quite wide support with one caveat: older versions of Internet Explorer don't support Element.dataset
. To cater to that userbase (0.34% of users at time of writing), you can use Element.getAttribute()
just the way Element.setAttribute()
is discussed above. Simply pass only one argument--the name of the attribute that you're trying to grab--and that attribute's value will be returned to you.
// We can still read a data attribute's value without dataset
var badges = element.getAttribute('data-badges');
Accessibility is a larger concern; always take the time to make your web creations as broadly accessible as you can. We need to make web technologies and learning resources freely available to ensure the growth and development of the web as a public platform.
The main accessibility concern in using data attributes is that assistive technology might not read them. Information that is important to the user should never be stated solely in a data attribute; be sure to restate any public-facing information in a traditional element on your page.
Putting Everything Together
Let's put together another example that uses data attributes across HTML, CSS, and JavaScript. Let's start with a blank HTML page.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Data Attributes</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style></style>
</head>
<body>
<script></script>
</body>
</html>
For this example, we'll put together a simple toolbar with a button that opens and closes a nav menu. Let's drop the necessary elements into the body
.
<body>
<header>
<h1>Toolbar</h1>
<button id="menu-btn">Menu</button>
</header>
<nav data-active="false">
<ul>
<li>News</li>
<li>About</li>
<li>Contact</li>
</ul>
</nav>
<script></script>
</body>
Notice that we put an id
attribute on our button so we can select it with confidence in our JavaScript and that we put a data attribute called active
on our nav
element.
Now let's add just a pinch of CSS to the page. In the HTML head
:
<style>
header {
background: #ccc;
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
All we're doing here is setting a background for our header to make it look a little more like a toolbar, and using some flex rules to spread the h1
and the button
inside the header
out to the edges.
Now let's think about what we want our button to do. Like the ever-present hamburger button, we just want it to open and close the nav menu. We'll use this behavior to take our data attribute knowledge for a spin.
So now let's add to our CSS:
nav[data-active="false"] {
display: none;
}
nav[data-active="true"] {
display: block;
}
Now when the active
data attribute is set to "true"
, it will be displayed, but when it's set to "false"
, it will not be displayed. With this added to the style
tag, the nav
element should disappear since we've written data-active="false"
.
To make the button work, we'll add JavaScript to the script
tag at the end of the HTML body
. Let's write a function to handle the toggling, and then attach it to click events on the button.
// First, grab our nav element
var nav = document.querySelector('nav');
// Then grab our menu button element
var menuButton = document.getElementById('menu-btn');
// Prepare a function to toggle the nav menu
var toggleNav = () => {
// Check the data attribute to see if the menu is currently
// active---notice that the data is a string
var active = (nav.dataset.active === 'true');
active = !active;
nav.setAttribute('data-active', active);
}
// Listen for clicks on the menu button and
// handle clicks with the above toggleNav function
menuButton.addEventListener('click', toggleNav);
If we run our example code in a browser, the button should show and hide the nav menu as expected. One note about reading data attributes in JavaScript: they always arrive as strings. We may want to parse the data into an integer using parseInt()
, translate it into a boolean as we do above with our active
data attribute, or otherwise parse the data into a more useful type. Just remember that data stored in data attributes is always treated as a string by HTML.
Wrap Up
One final note: working with data attributes won't be as fast as working with the values in a JavaScript object. Data attributes are powerful and in my opinion under-utilized, but like any other technique, remember that data attributes are just one tool on your toolbelt, and they should be a part of a larger weave of approaches that constitute a fully-featured solution. Try using data attributes to move quick hits of data around your code!
Top comments (0)