Хабрахабр

[Перевод] Полное руководство по HTML-атрибутам data-*

Представляем вашему вниманию перевод статьи, посвящённой использованию атрибутов data-*. Это — атрибуты, которые можно применять для удобного хранения в стандартных HTML-элементах различной полезной информации. Эта информация, в частности, может применяться в JavaScript и CSS.

Общие сведения

HTML-элементы могут иметь атрибуты, которые используются для решения самых разных задач — от предоставления данных ассистивным технологиям, до стилизации элементов.

<!-- Атрибут `class` можно использовать для стилизации в CSS, атрибут `role` используется ассистивными технологиями --><div class="names" role="region" aria-label="Names"></div>

При этом не рекомендуется создавать собственные атрибуты, или применять существующие атрибуты такими способами, на которые они не рассчитаны.

<!-- `highlight` не является HTML-атрибутом--><div highlight="true"></div> <!-- `large` не является допустимым значением для `width` --><div width="large">

Это плохо по многим причинам. HTML-код оказывается неправильно сформированным. И хотя подобное может и не иметь реальных негативных последствий, это лишает разработчика тёплого чувства вызываемого тем, что он создаёт валидный HTML-код. Но главная причина того, что так поступать не следует, заключается в том, что HTML — это язык, который постоянно развивается. В результате, если некий атрибут сегодня в языке не применяется, это не значит, что в будущем ничего не изменится.

Правда, если кому-то нужно использовать подобные атрибуты, у него есть совершенно нормальный способ это делать. Речь идёт о создании собственных атрибутов, названия которых начинаются с префикса data-. С этими атрибутами можно совершенно спокойно работать, применяя их так, как нужно программисту.

Синтаксис

Возможность создавать собственные HTML-атрибуты и записывать в них данные может оказаться крайне полезной. Это, как вы понимаете, возможно благодаря атрибутам data-*. Именно для этого такие атрибуты и предназначены. Выглядит это так:

<!-- Этим атрибутам необязательно назначать значения --><div data-foo></div> <!-- ...но они могут содержать значения --><div data-size="large"></div> <!-- Тут мы имеем дело с HTML, поэтому надо экранировать HTML-код, который, возможно, решено будет записать в атрибут --><li data-prefix="Careful with HTML in here."><li> <!-- Если надо - можно создавать длинные имена атрибутов --><aside data-some-long-attribute-name><aside>

Эти атрибуты, именно из-за того, что они всегда начинаются с префикса data-, часто называют атрибутами data-* или data-атрибутами. При формировании имён этих атрибутов сначала идёт слово data, потом — тире (-), а потом — оставшаяся часть имени, устроенная так, как нужно разработчику.

Можно ли использовать атрибут, имеющий имя data?

Вот пример кода, в котором используется атрибут с именем data:

<div data=""></div>

Атрибут с таким именем, вероятно, никому не повредит, но его применение не позволит пользоваться JavaScript-инструментами, которые мы рассмотрим ниже. В этом примере разработчик, фактически, создаёт некий собственный атрибут, что, как уже было сказано, делать не рекомендуется.

Чего не стоит делать с атрибутами data-*

В таких атрибутах не стоит хранить содержимое, которое должно быть доступно ассистивным технологиям. Если некие данные должны быть видимы на странице, или должны быть доступны средствам для чтения с экрана, их недостаточно просто поместить в атрибут data-*. Такие данные должны появиться и в обычной HTML-разметке.

<!-- Эти данные не выводятся на странице, они недоступны ассистивным технологиям --><div data-name="Chris Coyier"></div> <!-- Если нужен программный доступ к данным, но они не должны выводиться на странице, есть и другие способы... --><div> <span class="visually-hidden">Chris Coyier</span></div>

Вот материал о том, как скрывать элементы веб-страниц.

Стилизация элементов с использованием атрибутов data-*

В CSS можно выбирать HTML-элементы, основываясь на атрибутах и их значениях.

/* Выбрать элемент с таким именем атрибута, имеющим такое значение */[data-size="large"] { padding: 2rem; font-size: 125%;} /* Выбор можно ограничить элементом, классом, или чем-то другим */button[data-type="download"] { }.card[data-pad="extra"] { }

Это может показаться интересным. Для стилизации в HTML/CSS используются, в основном, классы. И хотя классы — это замечательный инструмент (они отличаются средним уровнем специфичности, с ними можно работать с помощью удобных JavaScript-методов через свойство элементов classList), элемент может либо иметь, либо не иметь некоего класса (то есть, класс в элементе либо «включен», либо «выключен»). При использовании атрибутов data-* в распоряжении разработчика оказываются и возможности классов («включено/выключено»), и возможность выбора элементов, основываясь на значении атрибута, которое он имеет на том же уровне специфичности.

/* Выбор элементов, у которых имеется указанный атрибут */[data-size] { } /* Выбор элемента, атрибут которого имеет заданное значение */[data-state="open"],[aria-expanded="true"] { } /* Селектор "начинается с", использование которого приведёт к выбору элементов, атрибут которых содержит "3", а так же - что угодно другое, начинающееся с 3 - вроде "3.14" */[data-version^="3"] { }/* Селектор "содержит" указывает на то, что заданная строка должна содержаться где-то в значении свойства */[data-company*="google"] { }

Специфичность селекторов атрибутов

Специфичность селекторов атрибутов такая же, как у классов. Специфичность часто рассматривают как значение, состоящее из 4 частей:

  • Встроенный стиль
  • ID
  • Классы и атрибуты
  • Теги

В результате, если представить себе значение специфичности для элемента, который стилизуется только с использованием селектора атрибута, то оно будет выглядеть так: 0, 0, 1, 0

А вот ещё один селектор:

div.card[data-foo="bar"] { }

Он уже будет описываться значением 0, 0, 2, 1. Число 2 здесь появляется из-за того, что тут имеется и класс (.card), и атрибут ([data-foo="bar"]). А 1 здесь из-за того, что тут присутствует лишь один тег (div).

Вот, чтобы было понятнее, иллюстрированная версия этих рассуждений.

1 тег, 1 класс и 1 атрибут

У селекторов атрибутов специфичность ниже, чем у идентификаторов (ID), но выше, чем у тегов (элементов). Их специфичность равна специфичности классов.

Значения атрибутов, нечувствительные к регистру

Если нужно, чтобы селекторы выбирали бы атрибуты, значения которых могут содержать строки, записанные с использованием разных комбинаций строчных и прописных букв, можно воспользоваться вариантом селектора, нечувствительным к регистру.

/* Всё это соответствует следующему селектору<div data-state="open"></div><div data-state="Open"></div><div data-state="OPEN"></div><div data-state="oPeN"></div>*/[data-state="open" i] { }

Такое поведение обеспечивает использование в селекторе символа i.

Вывод данных, хранящихся в атрибутах data-*

CSS позволяет извлекать значения атрибутов data-* и выводить их на странице.
 

/* <div data-emoji=":-)"> */ [data-emoji]::before { content: attr(data-emoji); /* Возвращает ':-)' */ margin-right: 5px;}

Примеры использования атрибутов data-* для стилизации элементов

Атрибуты data-* можно использовать для указания того, сколько столбцов должно быть у grid-контейнера. Вот HTML-код:

<div data-columns="2"> <div></div> <div></div> <div></div> <div></div></div> <div data-columns="3"> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div></div> <div data-columns="4"> <div></div> <div></div> <div></div> <div></div></div>

Вот соответствующий CSS-код:

[data-columns] { display: grid; grid-gap: 1rem; padding: 1rem; margin: 0 0 1rem 0;} [data-columns] > div { height: 100px; background: white;} [data-columns="2"] { background: #64B5F6; grid-template-columns: repeat(2, 1fr);} [data-columns="3"] { background: #9CCC65; grid-template-columns: repeat(3, 1fr);} [data-columns="4"] { background: #FFB74D; grid-template-columns: repeat(4, 1fr);}

А вот — фрагмент результирующей страницы.

Grid-контейнеры, настройка которых производится с помощью атрибутов data-*

Поэкспериментировать с этим примером можно на CodePen.

Работа с атрибутами data-* в JavaScript

К значениям атрибутов data-* можно обращаться, как и к значениям других атрибутов, пользуясь методом getAtribute для чтения данных, и методом setAttribute для записи.

// Чтение значения атрибутаlet value = el.getAttribute("data-state"); // Запись значения атрибута. // В data-state записывается значение "collapsed"el.setAttribute("data-state", "collapsed");

Однако атрибуты data-* имеют и собственный особый API. Предположим, у нас есть элемент с несколькими атрибутами data-* (что совершенно нормально):

<span data-info="123" data-index="2" data-prefix="Dr. " data-emoji-icon=":-)"></span>

Если имеется ссылка на этот элемент, то читать и записывать значения его атрибутов можно так:

// Чтениеspan.dataset.info; // 123span.dataset.index; // 2 // Записьspan.dataset.prefix = "Mr. ";span.dataset.emojiIcon = ";-)";

Обратите внимание на то, что в последней строке JS-кода используется запись имени атрибута в верблюжьем стиле. Система автоматически преобразует имена HTML-атрибутов, записанные в кебаб-стиле, в имена, записанные в верблюжьем стиле. То есть — data-this-little-piggy превращается в dataThisLittlePiggy.

Этот API, конечно, не такой удобный, как API classList, поддерживающий понятные методы вроде add, remove, toggle и replace, но это, всё же, лучше чем ничего.

В JavaScript можно работать и со встроенными в элементы наборами данных:

<img align="center" src="spaceship.png" data-ship-id="324" data-shields="72%" onclick="pewpew(this.dataset.shipId)"></img><h2><font color="#3AC1EF">JSON-данные в атрибутах data-*</font></h2><ul> <li data-person=' { "name": "Chris Coyier", "job": "Web Person" } '></li></ul>

А почему бы не записать в атрибут data-* JSON-данные? Ведь это всего лишь строки, которые можно отформатировать как валидные JSON-данные (учитывая кавычки и прочее). При необходимости эти данные можно извлечь из атрибута и распарсить.

const el = document.querySelector("li"); let json = el.dataset.person;let data = JSON.parse(json); console.log(data.name); // Chris Coyierconsole.log(data.job); // Web Person

Об использовании атрибутов data-* в JavaScript

Идея тут заключается в том, чтобы, пользуясь атрибутами data-*, размещать в HTML-коде данные, к которым можно обращаться из JavaScript для выполнения неких действий.

Распространённый вариант реализации этого сценария направлен на организацию работы с базами данных. Предположим, у нас имеется кнопка Like:

<button data-id="435432343">Like</button>

У этой кнопки может быть обработчик нажатия, выполняющий AJAX-запрос к серверу. Обработчик, если пользователь лайкнет что-то с помощью кнопки, увеличивает количество лайков в серверной базе данных. Обработчик знает о том, какую именно запись надо обновить, так как берёт сведения об этом из атрибута data-*.

Итоги

Вот, вот и вот — стандарты, связанные с селекторами атрибутов data-*. Здесь, на сайте Caniuse, можно узнать о поддержке атрибутов data-* браузерами. Если вы раньше не пользовались этими атрибутами, надеемся, этот материал дал вам пищу для размышлений.

Уважаемые читатели! Как вы применяете HTML-атрибуты data-*?

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»