Custom data-* Attributes

Attach your own structured data to any element, the standards-compliant way.

Sometimes you need to stash a bit of your own data on an element — a product id, a state flag, a config value. Inventing attributes like productid is invalid HTML. The sanctioned way is the data-* prefix.

The rules are simple

  • Any attribute starting with data- is valid: data-user-id, data-price, data-theme.
  • Read and write it from JavaScript through the dataset property.
  • Names convert from kebab-case to camelCase: data-user-id becomes element.dataset.userId.
<li data-id="42" data-price="9.99">Widget</li>

el.dataset.id     // "42"
el.dataset.price  // "9.99"

Bonus: CSS can see them too

Attribute selectors like [data-state="open"] let you drive styling from your data without touching classes — handy for state machines and toggles.

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A JavaScript event handler reads data-product-id from a clicked button to know which product to add to the cart.
  • A CSS selector uses [data-theme="dark"] to apply a dark-mode palette without adding extra class names.
  • A drag-and-drop list stores the item order in data-index on each element so the JS drop handler can reorder the array.

More examples

Data attribute read by JavaScript

dataset.productId maps camelCase to the hyphenated data-product-id attribute automatically.

Example · html
<button class="add-to-cart"
        data-product-id="42"
        data-product-name="HTML Course"
        data-price="29.00">
  Add to cart
</button>

<script>
  document.querySelector(".add-to-cart")
    .addEventListener("click", function() {
      const { productId, productName, price } = this.dataset;
      console.log(`Adding ${productName} (id:${productId}) at $${price}`);
    });
</script>

Data attribute targeted by CSS

CSS attribute selectors can directly target data attributes for state-driven styling without class toggling.

Example · html
<style>
  [data-theme="dark"] {
    background: #1a1a2e;
    color: #eaeaea;
  }
  [data-status="error"] {
    border: 2px solid red;
    background: #fff0f0;
  }
</style>

<div data-theme="dark">
  <input data-status="error" type="text">
  <p>Dark theme panel with error input.</p>
</div>

Pagination links with data attributes

Storing page numbers in data-page lets a single handler serve all pagination links without inline onclick.

Example · html
<nav aria-label="Pagination">
  <a href="#" data-page="1" class="page-link">1</a>
  <a href="#" data-page="2" class="page-link">2</a>
  <a href="#" data-page="3" class="page-link">3</a>
</nav>

<script>
  document.querySelectorAll(".page-link")
    .forEach(link => link.addEventListener("click", e => {
      e.preventDefault();
      loadPage(e.target.dataset.page);
    }));

  function loadPage(page) {
    console.log("Loading page", page);
  }
</script>

Discussion

  • Be the first to comment on this lesson.