Полное руководство по 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; // 123 span.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 Coyier console.log(data.job); // Web Person

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

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

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

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

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

Итоги

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

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

ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/490626/


Комментарии

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

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