A Complete Guide to Data Attributes
HTML elements can have attributes on them that are used for anything from accessibility information to stylistic control.
What is discouraged is making up your own attributes, or repurposing existing attributes for unrelated functionality.
There are a variety of reasons this is bad. Your HTML becomes invalid, which may not have any actual negative consequences, but robs you of that warm fuzzy valid HTML feeling. The most compelling reason is that HTML is a living language and just because attributes and values that don’t do anything today doesn’t mean they never will.
Good news though: you can make up your own attributes. You just need to prefix them with data-* and then you’re free to do what you please!
It can be awfully handy to be able to make up your own HTML attributes and put your own information inside them. Fortunately, you can! That’s exactly what data attributes are. They are like this:
Data attributes are often referred to as data-* attributes, as they are always formatted like that. The word data , then a dash — , then other text you can make up.
Can you use the data attribute alone?
It’s probably not going to hurt anything, but you won’t get the JavaScript API we’ll cover later in this guide. You’re essentially making up an attribute for yourself, which as I mentioned in the intro, is discouraged.
What not to do with data attributes
Store content that should be accessible. If the content should be seen or read on a page, don’t only put them in data attributes, but make sure that content is in the HTML content somewhere.
Styling with data attributes
/* Select any element with this data attribute and value */ [data-size="large"] < padding: 2rem; font-size: 125%; >/* You can scope it to an element or class or anything else */ button[data-type="download"] < >.card[data-pad="extra"]
This can be compelling. The predominant styling hooks in HTML/CSS are classes, and while classes are great (they have medium specificity and nice JavaScript methods via classList ) an element either has it or it doesn’t (essentially on or off). With data-* attributes, you get that on/off ability plus the ability to select based on the value it has at the same specificity level.
/* Selects if the attribute is present at all */ [data-size] < >/* Selects if the attribute has a particular value */ [data-state="open"], [aria-expanded="true"] < >/* "Starts with" selector, meaning this would match "3" or anything starting with 3, like "3.14" */ [data-version^="3"] < >/* "Contains" meaning if the value has the string anywhere inside it */ [data-company*="google"]
The specificity of attribute selectors
It’s the exact same as a class. We often think of specificity as a four-part value:
inline style, IDs, classes/attributes, tags
So a single attribute selector alone is 0, 0, 1, 0. A selector like this:
…would be 0, 0, 2, 1. The 2 is because there is one class ( .card ) and one attribute ( [data-foo=»bar»] ), and the 1 is because there is one tag ( div ).
Attribute selectors have less specificity than an ID, more than an element/tag, and the same as a class.
Case-insensitive attribute values
In case you’re needing to correct for possible capitalization inconsistencies in your data attributes, the attribute selector has a case-insensitive variant for that.
/* Will match */ [data-state="open" i]
It’s the little i within the bracketed selector.
Using data attributes visually
CSS allows you to yank out the data attribute value and display it if you need to.
You could use data attributes to specify how many columns you want a grid container to have.
Accessing data attributes in JavaScript
Like any other attribute, you can access the value with the generic method getAttribute .
let value = el.getAttribute("data-state"); // You can set the value as well. // Returns data-state="collapsed" el.setAttribute("data-state", "collapsed");
But data attributes have their own special API as well. Say you have an element with multiple data attributes (which is totally fine):
If you have a reference to that element, you can set and get the attributes like:
// Get span.dataset.info; // 123 span.dataset.index; // 2 // Set span.dataset.prefix = "Mr. "; span.dataset.emojiIcon = "🎪";
Note the camelCase usage on the last line there. It automatically converts kebab-style attributes in HTML, like data-this-little-piggy , to camelCase style in JavaScript, like dataThisLittlePiggy .
This API is arguably not quite as nice as classList with the clear add , remove , toggle , and replace methods, but it’s better than nothing.
You have access to inline datasets as well:
JSON data inside data attributes
Hey, why not? It’s just a string and it’s possible to format it as valid JSON (mind the quotes and such). You can yank that data and parse it as needed.
const el = document.querySelector("li"); let json = el.dataset.person; let data = JSON.parse(json); console.log(data.name); // Chris Coyier console.log(data.job); // Web Person
The concept is that you can use data attributes to put information in HTML that JavaScript may need access to do certain things.
A common one would have to do with database functionality. Say you have a “Like” button:
That button could have a click handler on it which performs an Ajax request to the server to increment the number of likes in a database on click. It knows which record to update because it gets it from the data attribute.
This browser support data is from Caniuse, which has more detail. A number indicates that browser supports the feature at that version and up.
Desktop
Mobile / Tablet
Атрибут data-*
В HTML 4 крайне не хватало возможности создавать свои собственные атрибуты для хранения значений. Зачем это надо? Вот несколько задач, где это может потребоваться.
- Создание всплывающих подсказок без применения скриптов.
- Определение стиля элемента на основе значения атрибута.
- Получение и изменение значений через скрипты.
В HTML5 появился новый универсальный атрибут, который можно добавлять к любому тегу. Правила написания атрибута простые:
- всегда начинаем с data-;
- используем только латинские буквы, дефис (-), двоеточие (:) и подчёркивание (_).
CSS и JavaScript немного по разному обращаются к таким атрибутам, так что разберём примеры для них отдельно.
CSS
В CSS есть атрибуты тегов, при наличии какого-либо атрибута или заданного значения мы задаём необходимый стиль.
Теперь можем в стилях обратиться к этому элементу как div[data-fluid] и установить для него нужное оформление. В общем, это напоминает работу классов, поэтому не является какой-то уникальной или необходимой фичей. Так что полезнее задавать значения.
В CSS после этого можем задавать разный стиль при различных значениях нашего атрибута data-columns.
div[data-columns=2] < width: 480px; >div[data-columns=3]
Опять же, это в какой-то мере является заменой классам, ничего ведь не мешает сделать классы с именами column-2, column-3 и добавлять их при необходимости.
Более изящной областью применения выступает включение функции attr() . Она получает значение заданного атрибута и вставляет его в стиль. Удобно это использовать для создания всплывающих подсказок. Текст пишем прямо внутри элемента, а вывод и оформление подсказки реализуем с помощью CSS.
meter < position: relative; >meter:hover::after Температура воды
В данном примере к элементу добавляется атрибут data-description содержащий необходимый текст для вывода. Само отображение происходит с помощью псевдоэлемента ::after и свойства content , значением которого как раз и выступает функция attr() .
JavaScript
Если в CSS мы обращаемся к имени атрибута напрямую, указывая его полностью, то в JavaScript это делается через метод dataset. Само имя атрибута преобразовывается в переменную по следующим правилам:
- data- отбрасывается;
- любой дефис идущий перед буквой отбрасывается, а буква за ним становится заглавной.
На практике это выглядит так.
data-description превращается в description.
data-full-description превращается fullDescription.
data-description-of-tag превращается descriptionOfTag.
Традиционный способ получить доступ к элементу и его атрибутам — задать идентификатор и обратиться к элементу через getElementById , как показано в примере ниже.
Пользователь
Вначале добавляем к элементу идентификатор с уникальным значением. Затем получаем доступ к элементу через getElementById . Теперь мы можем обращаться к любым атрибутам data через метод dataset , причём не только получать, но и устанавливать значения. Храниться они будут до перезагрузки страницы или до установки нового значения.
См. также
HTML-атрибуты data-* для хранения параметров и получения их в js
В HTML 5 были введены такие атрибуты тегов, как data-*.
Про них вы наверняка слышали или видели в разных проектах.
Например, их используют такие модные товарищи, как Twitter Bootstrap и jQuery Mobile.
Раньше использовали классы, ради сохранения информации в HTML, с целью последующего использования в js.
Например, для сохранения уникального номера блока часто пишут так:
А если нам нужно добавить еще один класс для каждого элемента? Или модификатор для отдельных? Да, конечно, можно обрезать регуляркой или другим костыликом на ваш вкус.
Как может показаться, тут можно задействовать id, но у нас могут быть блоки с одинаковым номером.
Иногда используют атрибут ‘rel’, но его можно использовать только для ссылок, хотя я видел и у других элементов. И опять же недостаток — мы можем записать в него только одно значение.
И вот нам на помощь спешат Чип и Дейл атрибуты data-*.
Плюшки
Можно присобачить к любому тегу и старые браузеры ничего не скажут против.
Можно в названии писать словосочетания: data-email-id=”190”.
Можно использовать любую строку в значении.
Можно использовать любой количество таких параметров для одного тега.
HTML тогда превратится в это:
Теперь самое интересное, а именно — работа в jQuery.
Находим: $(‘[data-email-id]’) или $(‘[data-action=close]’) или даже $(‘[data-date^=2010]’)
Получаем значение: var email = $(selector).attr(‘data-email-id’)
Самое интересное — это использование функции .data().
В версии 1.4.3 data() научилось получать наши атрибуты data-* вот таким образом:
var action = $(selector).data(‘action’); // close
Если же мы использовали словосочетание через дефис, то мы сможем получить его в camelCase:
Один минус (а может и не минус) — это то, что в data() сохранится только изначальное значение (кешируется), и если мы изменим значение атрибута (например, через .attr(‘data-foo-bar’, 456)), то получая .data(‘fooBar’) увидим наше старое значение.
Но никто не мешает нам обновлять значение в 2х местах, если мы так захотим:
var baz = 150; $(selector).data('fooBar', baz).attr('data-foo-bar', baz);
Хотя, если вам не нужно отслеживать код в, например, фаербаге, то можно и не обновлять .attr(), так как он влияет только на “визуальное” отображение.
В общем, как только вам понабиться сохранить дополнительные параметры в теге, то используйте data-атрибуты.
ЗЫ:
Интересно, кто нибудь пробовал хранить в атрибутах json? 🙂
Хотя это, пожалуй, в ненормальное программирование.
ЗЫЫ:
Многие говорят про функцию jQuery.data(elem, key, [value])
Кто не знает, эта функция отличается от $(selector).data(key, [value])
Она позволяет привязывать данные к DOM-элементам любым объектам, а не к jQuery объектам. Да, она работает на 60% быстрей, но вот data-* атрибуты она не получает.