If you need to attach custom attributes to an HTMLElement
that you can also access from JavaScript
or CSS
,
please use data-attributes
.
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="..."
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
.
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; }
<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>
https://developer.mozilla.org/en-US/docs/Web/HTML/How_to/Use_data_attributes
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dataset#in_html