Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Казалось бы, простая задача - сверстать список пар ключ-значение. Бери <div>
и делай. Но что, если захотелось подушнить? Этим и займёмся в статье...
Рассмотрим три подхода к решению этой задачи: <div>
, <dl>, <dt>, и <dd>
, и <table>
. Обсудим преимущества, недостатки, взглянем на примеры.
Цель - разобраться с выбором наиболее подходящего подхода для решения задачи.
Задача, дано
<Input>
, принимающий ИНН организации. Стучится в дадату, возвращает данные, создает выпадающий список и даёт пользователю выбрать нужное.
Далее определяется несколько пар ключ-значение для каждой организации. Простой объект:
{
companyName: "ООО "Моя оборона",
inn: 1234567890,
kpp: 1234567890,
address: "Улица Пушкина дом Колотушкина"
}
Решение №1 <div>
Это самый простой и прямолинейный подход, который легко реализовать.
<div class="company">
<div class="inn"><span>ИНН</span>: <span>1234567890</span></div>
<div class="kpp"><span>КПП</span>: <span>1234567890</span></div>
<div class="address"><span>Адрес</span>: <span>Улица Пушкина дом Колотушкина</span></div>
</div>
Помимо простоты, это самый легковесный вариант. 5 строк и несколько элементов. Стилизовать такой вариант получается намного быстрее следующих.
Однако, смотрим в документацию и видим, что <div> используется когда ни один другой элемент не подходит, элемент div используется в качестве крайней меры. В противном случае это приводит к снижению доступности для читателя. Также Согласно руководству W3C по доступности веб-контента (WCAG):
информация, структура и отношения, передаваемые через презентацию, должны быть доступны программно. Это означает, что структура пар ключ-значение должна быть ясно выражена в разметке, а не только в визуальном представлении
Выходит, данное решение не удовлетворяет принципу устойчивости (robust) WCAG 2, использованию правильной семантической верстки. Хорошо, тогда попробуем второе решение.
Решение №2 <dl> <dt> <dd>
Элементы <dl>
, <dt>
, <dd>
предназначены для представления пар ключ-значение. Список - термин - описание могут смутить, поэтому обратимся к документации w3.org
<dl>
элемент предоставляет ассоциативный список, состоящий из нуля или более групп имя-значение.
...
Группы "Имя-значение" (<dt>
и<dd>
соответственно) могут представлять собой термины и определения, разделы метаданных и значения, вопросы и ответы или любые другие группы данных "имя-значение"
В контексте HTML, “термин” в <dt>
может быть более широко интерпретирован, чем просто академический или словарный термин. Он может обозначать любой элемент данных, который имеет связанное с ним значение. Так что использование ИНН и номера в качестве “терминов” вполне приемлемо.
<dl>
<dt>ООО "Моя оборона"</dt>
<dd>
<dl>
<dt>ИНН</dt>
<dd>1234567890</dd>
<dt>КПП</dt>
<dd>1234567890</dd>
<dt>Адрес</dt>
<dd>Улица Пушкина дом Колотушкина</dd>
</dl>
</dd>
</dl>
Принцип устойчивости WCAG тоже соблюдён. А скринридер распознает эти элементы как определения, причем читая их последовательно:
Термин "ООО Моя оборона" -> термин "ИНН" -> 1234567889 -> термин "КПП" -> 1234567890 -> термин "Адрес" -> Улица Пушкина дом Колотушкина.
Стилизовать такой вариант немного сложнее, чем первое решение. Однако, здесь возникает еще один вопрос - не табличные ли это данные? Ведь здесь есть её признаки:
Структура таблицы включает в себя две базовые части:
Подлежащее — это признак, по которому данные группировали и обрабатывали.
Сказуемое — это данные, которые раскрывают суть подлежащего.
Решение №3 <table>
Элемент <table> предназначен для представления табличных данных. С одной стороны, можно представить решение задачи как список таблиц вида:
ИНН | 1234567890 |
КПП | 1234567890 |
Адрес | Улица Пушкина дом Колотушкина |
Несмотря на то, что выше представлена простая таблица, данные в ней не группированы. По сути это выборка данных из общей таблицы, которая должна бы выглядеть иначе. Взглянем на верстку:
<table>
<thead>
<tr>
<th colspan="2">ООО "Моя оборона"</th>
</tr>
</thead>
<tbody>
<tr>
<td>ИНН</td>
<td>1234567890</td>
</tr>
<tr>
<td>КПП</td>
<td>1234567890</td>
</tr>
<tr>
<td>Адрес</td>
<td>Улица Пушкина дом Колотушкина</td>
</tr>
</tbody>
</table>
Получилось громоздко. Скринридер увидит, что к "ООО Моя оборона" относится целая табличная часть, но читать он ее будет криво:
ООО "Моя оборона" -> ИНН -> ООО "Моя оборона" -> 1234567890 > ООО "Моя оборона" -> КПП -> ООО "Моя оборона" -> ....
Как исправить ситуацию? Переверстать всё в одну таблицу и сгруппировать данные:
Название компании | ИНН | КПП | Адрес |
ООО "Моя оборона" | 1234567890 | 1234567890 | Улица Пушкина дом Колотушкина |
ООО "Рога и копыта" | 2234567890 | 2234567890 | Улица Гагарина в гостях у Татарина |
Теперь это действительно таблица со сгруппированными данными. У таблицы есть "шапка" и "тело" и у скринридера не возникнет неполадок. Также в таком случае получится удовлетворить и требования WCAG. Однако, визуально задача будет решена неверно, ведь необходимостью было присвоить каждому элементу найденного списка отдельную сущность.
Заключение
Таким образом, в случае задачи сверстать список пар ключ-значение, удовлетворив требования семантики и доступности, необходимо выбирать Решение №2 <dl>
<dt>
<dd>
.
А если нужно грубо и быстро, то классический и самый популярный вариант с <div>