DEV Community

Cover image for HTML Data Attributes: One of the Original State Management Libraries
Nick Taylor
Nick Taylor

Posted on • Updated on • Originally published at nickyt.co

HTML Data Attributes: One of the Original State Management Libraries

I was streaming recently and discussed how I implemented part of a graph I was building out.

The graph is interactive, where you can navigate with the keyboard or hover over parts of the graph and a list item is bolded.

A graph component showing the most used programming languages with a horizontal bar that has different colours whose widths are the percentage of each most used language. As items are hovered or given focus with the keyboard, the associate language text and percentage is bolded.

Here's the pull request.

feat: add most used languages graph #2158

Description

Adds the Most Used Languages Graph to our components. A follow up PR will integrated the graph in the site.

What type of PR is this? (check all applicable)

  • [x] 🍕 Feature
  • [ ] 🐛 Bug Fix
  • [ ] 📝 Documentation Update
  • [ ] 🎨 Style
  • [ ] 🧑‍💻 Code Refactor
  • [ ] 🔥 Performance Improvements
  • [ ] ✅ Test
  • [ ] 🤖 Build
  • [ ] 🔁 CI
  • [ ] 📦 Chore (Release)
  • [ ] ⏩ Revert

Related Tickets & Documents

Closes #1602

Mobile & Desktop Screenshots/Recordings

Graph

CleanShot 2023-11-17 at 10 30 47

Graph Loading

CleanShot 2023-11-16 at 14 29 43

Added tests?

  • [ ] 👍 yes
  • [x] 🙅 no, because they aren't needed
  • [ ] 🙋 no, because I need help

Added to documentation?

  • [ ] 📜 README.md
  • [ ] 📓 docs.opensauced.pizza
  • [ ] 🍕 dev.to/opensauced
  • [x] 📕 storybook
  • [ ] 🙅 no documentation needed

[optional] Are there any post-deployment tasks we need to perform?

[optional] What gif best describes this PR or how it makes you feel?

So what's this have to do with HTML data attributes? Well, before we get into that, what is an HTML data attribute? And what is an HTML attribute?

HTML elements have a predefined set of attributes that are valid attributes. You are probably familiar with a lot of them.

For example, a text input, is an input HTML element that has a type equal to text. type is an attribute.

Another one you are likely familiar with is class. This is the attribute you use to add one or more CSS classes to an HTML tag.

<a href="/awesome-product" class="funky-link">Awesome Product</a>
Enter fullscreen mode Exit fullscreen mode

Note: If you've worked mainly with React, the className prop on a component generates an HTML class attribute when your component renders.

You can create non-standard attributes, like item or productId that will work, but if you want to access them, you would have to access them via the attribute getter, e.g.

// Get the awesome product HTML element.
const someElement = document.querySelector('#awesome-product');

// get attribute returns the value or if there is none, it returns null
const productId = someElement.getAttribute('productId');
Enter fullscreen mode Exit fullscreen mode

If you have a lot of these bespoke attributes, you'll always have to use .getAttribute().

Insert "There must be a better way" GIF here. 🤣

There is a better standard way to go about this, data attributes. Data attributes are a standard part of HTML. All you need to do is have them begin with data- and if the rest of the attribute is more than one word, separate them with hyphens.

For example, our productId would now become data-product-id. That looks like many extra characters, and we're still using .getAttribute.

Although, .getAttribute works, it's not necessary. HTML elements, when accessed via JavaScript, have a special property called, dataset. The dataset property contains all the data-* attributes.

So for example, if I wanted to get the value of the data-product-id attribute, I can do the following:

// Get the awesome product HTML element.
const someElement = document.querySelector('#awesome-product');

const productId = someElement.dataset.productId
Enter fullscreen mode Exit fullscreen mode

So a few things are happening under the hood. All the data attributes when accessed via the dataset property no longer have data- in their names, and when the attribute has more than one word in it like data-product-id, it gets converted to camel case, productId.

The real power of this is if there are several of these attributes on an element, they're all available under the dataset property.

As mentioned at the beginning, I'm currently using a data attribute in the graph I made, but if you happen to be reading this on dev.to, they leverage data attributes quite a bit.

DEV is a Rails monolith, which uses Preact in the front-end using islands architecture. The reason why I mention all this is that it's not a full-stack JavaScript application, and there is no state management library like Redux or Zustand in use. The data store, for the most part on the front end, is all data attributes.

If you use the browser tools to inspect the home page of DEV, you'll see that the body HTML element is jam packed with data attributes.

some of the markup from the dev.to homepage showing data attributes in use on DEV

State management libraries are definitely useful in certain contexts, but sometimes leveraging what the platform gives you, like data attributes, can be beneficial for your use case.

<p data-bye="That's all folks">Later</p>

Top comments (11)

Collapse
 
viniciusferreira profile image
Vinícius Ferreira

👋🏻 Nick

Loved your piece! 👏🏻

Just a quick tip: I looked at the PR and you can leverage Tailwind's group, data, focus and hover utilities to conditionaly apply styles, no JS needed.

Here's an example of something similar:

<div data-size="medium" class="group/root">
  <div class="group-data-[size=large]/root:p-8">
    <!-- Will not apply `p-8` -->
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

from github.com/tailwindlabs/tailwindcs...

Keep up the great work!

Cheers!

Collapse
 
viniciusferreira profile image
Vinícius Ferreira

Check 'first', 'last' and the other modifiers too, they can help with a lot more 😄

tailwindcss.com/docs/hover-focus-a...

Collapse
 
nickytonline profile image
Nick Taylor

Nice! This is the first project I've used Tailwind in, so thanks for the tips!

Hot Rod saying Cool beans!

Thread Thread
 
viniciusferreira profile image
Vinícius Ferreira

Hope you enjoy Tailwind! You can DM me @constVinicius if you need help with those utilities 👷🏻‍♂️🛠

Collapse
 
codingjlu profile image
codingjlu

I love the creativity here. I do think, however, that calling data attributes a state management library is a bit of a stretch, as it lacks key built-in features like subscriptions and access everywhere. Just listening for a change in data attributes is hectic, requiring lots of boilerplate cruft using mutation observers and the such... the only straightforward way I can see this is with using web components, but managing other components' states are still wildly complicated, and thus I don't think it really solves the final state management problem as a whole. Thoughts?

Collapse
 
nickytonline profile image
Nick Taylor

Thanks for giving it a read @codingjlu!

It's definitely not a full-blown state management library. 😅 I was being cheeky/click baity by saying that.

The point was to more leverage what's in your browser for state when it makes sense, like the URL and data-attributes.

Collapse
 
codingjlu profile image
codingjlu

Got it, and I'm all for frameworkless stuff, so this resonates quite a bit. 👍

Collapse
 
aminiyehia1 profile image
Amini Yehia

nice article

Collapse
 
nickytonline profile image
Nick Taylor

Thanks Amini!

Captain America saluting

Collapse
 
arodriguezhacks profile image
Angie Rodriguez

Helpful article, thank you for putting it together and providing good context for how data attributes came into existence.

Collapse
 
nickytonline profile image
Nick Taylor

Thanks for the kind words Angie. Gald you liked it!