Data attributes
HTML lets you add your own attributes as long as their names start with data-. They are a clean way to give your scripts information without hiding it in classes or ids:
<button class="add" data-product-id="42" data-price="1200" data-in-stock="true">Add to cart</button>Browsers ignore these attributes, CSS can read them, and JavaScript can read them. jQuery's .data() makes reading them convenient.
Reading with .data()
<button id="buy" data-product-id="42" data-price="1200.50" data-in-stock="true" data-tags='["desk","oak"]' data-name="Oak desk">Buy</button>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $b = $("#buy");
console.log("productId:", $b.data("productId"), typeof $b.data("productId"));
console.log("price:", $b.data("price"), typeof $b.data("price"));
console.log("inStock:", $b.data("inStock"), typeof $b.data("inStock"));
console.log("tags:", $b.data("tags").length, "tags, first is", $b.data("tags")[0]);
console.log("name:", $b.data("name"));
console.log("all:", JSON.stringify($b.data()));
</script>productId: 42 number
price: 1200.50 string
inStock: true boolean
tags: 2 tags, first is desk
name: Oak desk
all: {"productId":42,"price":"1200.50","inStock":true,"tags":["desk","oak"],"name":"Oak desk"}Two things happen automatically:
- Names become camelCase.
data-product-idis read asproductId,data-in-stockasinStock. - Values are converted. Strings that look like numbers become numbers,
"true"and"false"become booleans,"null"becomesnull, and text that looks like a JSON object or array is parsed.
With no argument, .data() returns an object containing every data value of the element. Look at the price, though: it stayed a string. The next section explains why.
When conversion does not happen
jQuery only turns a string into a number if turning it back gives exactly the same string. This protects values that look like numbers but are not:
<span id="s" data-zip="007" data-price="1.50" data-code="12" data-big="1e3"></span>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $s = $("#s");
for (const key of ["zip", "price", "code", "big"]) {
console.log(key, JSON.stringify($s.data(key)), typeof $s.data(key));
}
</script>zip "007" string
price "1.50" string
code 12 number
big "1e3" string"007" and "1.50" stay strings, because as numbers they would become 7 and 1.5. "12" becomes the number 12. If you need a value to be a number every time, convert it yourself with Number(); if you need the exact text, read it with .attr().
Using data attributes in a handler
Data attributes shine when many elements share one click handler:
<div>
<button data-product-id="7" data-name="Desk lamp" data-price="1200">Add lamp</button>
<button data-product-id="9" data-name="Notebook" data-price="150">Add notebook</button>
</div>
<p id="cart">Cart is empty</p>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
$("button").on("click", function () {
const item = $(this).data();
$("#cart").text("Added " + item.name + " (#" + item.productId + ") for " + item.price);
console.log(item.productId + item.price);
});
</script>159The logged sum shows that productId and price really are numbers: 9 + 150 = 159, not the string "9150".
Storing your own values
.data(key, value) attaches any JavaScript value to an element: numbers, objects, even functions. It is kept in jQuery's internal memory, not in the HTML:
<div id="widget" data-status="new">Widget</div>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
const $w = $("#widget");
$w.data("status", "saved");
$w.data("settings", { theme: "dark", size: 3 });
console.log("data status:", $w.data("status"));
console.log("attr status:", $w.attr("data-status"));
console.log("settings size:", $w.data("settings").size);
$w.removeData("status");
console.log("after removeData:", $w.data("status"));
</script>data status: saved
attr status: new
settings size: 3
after removeData: newNotice three things:
- After setting
statustosaved, the attribute still saysnew..data()does not write to the HTML. - jQuery reads the attribute only the first time; after that, it uses its stored value.
.removeData("status")deletes the stored value, so the next read falls back to the attribute again.
.data() or .attr()?
| Situation | Use |
|---|---|
| Reading configuration from HTML as real types | .data() |
| Keeping state for an element in your script | .data(key, value) |
A CSS rule depends on the attribute, e.g. [data-state="open"] |
.attr("data-state", "open") |
| You need the exact string, e.g. a code with leading zeros | .attr("data-code") |
The plain JavaScript equivalent is the dataset property: element.dataset.productId. It always returns strings, and setting it does update the attribute.
Common mistakes
- Expecting
.data(key, value)to change the attribute and CSS selectors that use it. - Changing the attribute with
.attr()after.data()has read it, then reading.data()again and getting the old value. - Relying on automatic conversion for codes, phone numbers and postcodes.
- Using hyphenated keys inconsistently. Pick camelCase in your code.
Exercise
Give three list items a data-rating from 1 to 5. Use .data() to find the item with the highest rating and make it bold.
Show one possible answer
<ul><li data-rating="3">Lamp</li><li data-rating="5">Desk</li><li data-rating="4">Chair</li></ul>
<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
let $best = $();
$("li").each(function () {
if (!$best.length || $(this).data("rating") > $best.data("rating")) $best = $(this);
});
$best.css("font-weight", "bold");
console.log($best.text());
</script>Desk$() with no argument creates an empty selection, a handy starting value.
Key points
- HTML data- attributes such as data-product-id hold extra information for your scripts.
- .data("productId") reads data-product-id and converts numbers, true/false and JSON into real values.
- .data(key, value) stores a value in jQuery's memory; it does not change the HTML attribute.
- Use .attr("data-...") when you need the exact string, or when CSS or other code reads the attribute.