Please Use HTML data-attributes

July 27, 2025

If you need to attach custom attributes to an HTMLElement that you can also access from JavaScript or CSS, please use data-attributes.

HTML

Let’s say you have a very simple gallery that has image thumbnails and it displays the full image when you click on a thumbnail and also displays a caption for the image, we can define this gallery in HTML as follows:

<div id="gallery">
  <img
    src="thumb1.jpg"
    alt="Sunrise thumbnail"
    class="thumbnail"
    data-full-src="images/sunrise.jpg"
    data-caption="Sunrise over the mountains"
    >
  <img
    src="thumb2.jpg"
    alt="City skyline thumbnail"
    class="thumbnail"
    data-full-src="images/skyline.jpg"
    data-caption="Nighttime city skyline"
    >
</div>

<div id="lightbox" class="hidden">
  <button id="close-btn">❌</button>
  <img id="lightbox-img" alt="">
  <p id="lightbox-caption"></p>
</div>

Notice how for each image we used 2 attributes that start with data-:

data-full-src="..."
data-caption="..."

JavaScript

These allow us to hold the data related to the image in a semantic way, we can then access this data via a uniform API from JavaScript:

const gallery      = document.getElementById('gallery');
const lightbox     = document.getElementById('lightbox');
const lbImg        = document.getElementById('lightbox-img');
const lbCaption    = document.getElementById('lightbox-caption');
const closeBtn     = document.getElementById('close-btn');

gallery.addEventListener('click', e => {
  const thumb = e.target.closest('.thumbnail');
  if (!thumb) return;

  const fullSrc = thumb.dataset.fullSrc;
  const caption = thumb.dataset.caption;

  lbImg.src         = fullSrc;
  lbImg.alt         = thumb.alt;
  lbCaption.textContent = caption;

  lightbox.classList.remove('hidden');
});

closeBtn.addEventListener('click', () => {
  lightbox.classList.add('hidden');
  lbImg.src = '';
});

The important part to notice here is the use of the dataset read-only property on an element

...
  const fullSrc = thumb.dataset.fullSrc;
  const caption = thumb.dataset.caption;
...

you’ll also notice that, conveniently, we access these data attributes in camelCase.

CSS

Additionally, you can also access these attributes in CSS, let’s say you want to style the thumbnails based on the data-caption, you could do something like this:

.thumbnail[data-caption*="night"] { border: 2px solid gold; }

Full Example

<html>
  <head>
    <style>
      .hidden { display: none; }
      #lightbox {
          position: fixed; top: 0; left: 0; width: 100%; height: 100%;
          background: rgba(0,0,0,0.8); text-align: center; padding-top: 50px;
      }
      #lightbox-img {
          max-width: 80%;
          max-height: 70%;
      }
      #lightbox-caption { color: white; margin-top: 10px; }
      #close-btn {
          position: absolute; top: 10px; right: 20px;
          font-size: 2rem; color: white; background: none; border: none;
          cursor: pointer;
      }
    </style>
  </head>
  <body>
    <div id="gallery">
      <img
        src="thumb1.jpeg"
        alt="Sunrise thumbnail"
        class="thumbnail"
        data-full-src="images/sunrise.jpg"
        data-caption="Sunrise over the mountains"
        >
      <img
        src="thumb2.jpeg"
        alt="City skyline thumbnail"
        class="thumbnail"
        data-full-src="images/skyline.jpg"
        data-caption="Nighttime city skyline"
        >
    </div>

    <div id="lightbox" class="hidden">
      <button id="close-btn">❌</button>
      <img id="lightbox-img" alt="">
      <p id="lightbox-caption"></p>
    </div>

    <script>
      const gallery      = document.getElementById('gallery');
      const lightbox     = document.getElementById('lightbox');
      const lbImg        = document.getElementById('lightbox-img');
      const lbCaption    = document.getElementById('lightbox-caption');
      const closeBtn     = document.getElementById('close-btn');

      gallery.addEventListener('click', e => {
          const thumb = e.target.closest('.thumbnail');
          if (!thumb) return;

          const fullSrc = thumb.dataset.fullSrc;
          const caption = thumb.dataset.caption;

          lbImg.src         = fullSrc;
          lbImg.alt         = thumb.alt;
          lbCaption.textContent = caption;

          lightbox.classList.remove('hidden');
      });

      closeBtn.addEventListener('click', () => {
          lightbox.classList.add('hidden');
          lbImg.src = '';
      });
    </script>
  </body>
</html>

References