Тег dl в HTML: список определений, группы dt и dd и стили

Тег dl (от английского description list, «список описаний») собирает пары «название и значение». Внутри него записывают группы: dt (description term) задаёт название, а dd (description details) — значение или описание. Это парные теги, закрывающие </dt> и </dd> можно опустить. Браузер выводит название с новой строки, а описание сдвигает вправо: ни маркеров, ни номеров у такого списка нет.

Урок «Когда использовать dl вместо обычного списка» объясняет, когда вместо обычного списка нужен dl. Здесь разберём другое: как записать группы так, чтобы разметка прошла проверку, собрать две колонки без сбоя при двух dd, сделать адаптив и точки-заполнители в прайсе.

HTML
<dl>
  <dt>HTML</dt>
  <dd>Язык разметки страниц</dd>
  <dt>CSS</dt>
  <dd>Язык стилей страниц</dd>
</dl>

Тег dl в HTML: что это и из чего состоит список определений

Тег dl блочный: он занимает всю ширину и отделяется от соседей отступами 1em сверху и снизу (16px при шрифте 16px). Название dt выводится обычным шрифтом, а не жирным, как часто думают. Описание dd получает отступ слева 40px. Других стилей у этих трёх тегов нет, поэтому весь вид настраивается в CSS.

CSS браузера
dl {
  margin: 1em 0;
}
dd {
  margin-inline-start: 40px;
}

Пример: пары в списке dl и стили по умолчанию

Результат

Выберите список: под результатом отступы и шрифт, которые браузер вычислил для этого списка.

Где можно записать тег dl и что допустимо внутри него

Сам dl записывают там, где допустим блок: в div, section, li, dd и прямо в теле страницы. Вложенный список определений записывают внутри dd, а не внутри самого dl. Внутри dl допустимы только dt, dd и обёртки div: текст, p и span валидатор считает ошибкой. Запись dl внутри абзаца p тоже неверна: браузер закрывает абзац перед списком, а лишний </p> создаёт пустой абзац.

HTML
<div>
  <dl>
    <dt>Цвет</dt>
    <dd>Зелёный</dd>
  </dl>
</div>

Пример: где допустим dl и что нельзя записать внутри

Результат

Выберите запись: вверху её код, под результатом написано, допустима ли она. Для dl в p показано дерево, которое построил браузер.

Группы dt и dd в теге dl: один к одному и один ко многим

Группа в dl состоит из одного или нескольких dt, за которыми идут один или несколько dd. Поэтому допустимы три схемы: один dt и один dd, несколько dt на одно dd (синонимы) и один dt с несколькими dd (несколько значений). Первым в группе всегда идёт dt, а dt без dd валидатор считает ошибкой. Одно название дважды в одном dl даёт предупреждение: значения лучше собрать под одним dt.

HTML
<dl>
  <dt>Страна</dt>
  <dd>Япония</dd>
  <dd>Китай</dd>
</dl>

Пример: допустимые и неверные группы dt и dd

Результат

Выберите запись: вверху код, под результатом вывод валидатора. Для записи без закрывающих тегов показано дерево браузера.

Тег dl с div-обёрткой: одна группа - один div

Чтобы оформить группу целиком (линия, фон, рамка), её записывают в div. Стандарт разрешает такую обёртку, а смысл списка при этом не меняется. Правило одно: один div вмещает одну группу, то есть один или несколько dt и за ними один или несколько dd. Нельзя записывать две группы в один div, смешивать обёрнутые и необёрнутые группы, вкладывать div в div и оставлять в div один dt. Подробнее про блок div рассказывает страница про тег div.

HTML
<dl>
  <div>
    <dt>Цвет</dt>
    <dd>Зелёный</dd>
  </div>
  <div>
    <dt>Вес</dt>
    <dd>100 г</dd>
  </div>
</dl>

Пример: div вокруг группы и неверные обёртки

Результат

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

Что записать внутри dt и dd тега dl: p, ul, a и вложенный dl

В dd допустим любой поток: абзацы, списки, ссылки тега a, картинки, таблицы и вложенный dl. У вложенного dd те же 40px, поэтому отступы складываются. Обычно в dt записывают короткий строчный текст: strong, span, abbr. Заголовки, header, footer и секции внутри dt не допускаются.

HTML
<dl>
  <dt>Чай</dt>
  <dd>
    <p>Бывает разный.</p>
    <ul>
      <li>Зелёный</li>
      <li>Чёрный</li>
    </ul>
  </dd>
</dl>

Пример: что записать внутри dt и dd

Результат

Выберите запись: вверху код, под результатом вывод. У вложенного dl показаны отступы, которые измерил браузер.

Для чего нужен тег dl: характеристики, глоссарий, вопросы и ответы

Тег dl подходит там, где у каждого значения есть название: характеристики товара, глоссарий, контакты, рецепт с граммовками, вопросы и ответы. Это не только термины: стандарт прямо допускает метаданные и пары «вопрос и ответ». Если у пунктов названий нет, нужен обычный список ul, а если у каждой строки несколько значений в колонках, нужна таблица table.

HTML
<dl>
  <dt>Можно ли вернуть товар?</dt>
  <dd>Да, в течение 14 дней.</dd>
</dl>

Пример: что записать в dl, а что нет

Результат

Выберите задачу: вверху разметка, под результатом написано, подходит ли для неё dl.

Отступы тега dl по умолчанию: margin у dl и dd

Отступы задают три правила браузера: margin по 1em сверху и снизу у самого dl и margin-inline-start: 40px у dd. Свойство inline-start следует направлению письма: при dir="rtl" отступ у dd оказывается справа, а не слева. Чтобы убрать отступ слева, записывают margin: 0 у dd, а если нужен отступ без сдвига блока, добавляют padding-left.

CSS
dd {
  margin: 0;
  padding-left: 20px;
}

Пример: отступы dl и dd

Результат

Выберите правило: под результатом отступы, которые вычислил браузер.

Две колонки в теге dl через grid и ловушка с двумя dd

Две колонки собирают через display: grid у dl: каждый dt попадает в первую колонку, каждый dd — во вторую, а margin у dd нужно обнулить. Но сетка заполняется по порядку, поэтому при двух dd на один dt второй dd занимает первую колонку, а следующий dt сдвигается во вторую, и сбой идёт до конца списка. Исправляют явными колонками: dt в первую, dd во вторую. Обёртка div с display: contents действует так же, как её отсутствие, а div со своей сеткой удерживает сбой внутри группы, но второй dd всё равно попадает в первую колонку.

CSS
dl {
  display: grid;
  grid-template-columns: 120px 1fr;
}
dt {
  grid-column: 1;
}
dd {
  margin: 0;
  grid-column: 2;
}

Пример: колонки dl и сбой с двумя dd

Результат

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

Адаптивный тег dl: одна колонка на узком блоке

На узком блоке две колонки сжимают значение до нескольких букв. Вместо @media, который смотрит на ширину окна, лучше правило @container: оно смотрит на ширину самого блока, поэтому список одинаково ведёт себя и в боковой колонке, и на всю страницу. Блоку-обёртке задают container-type: inline-size, а при узкой ширине сетку переводят в одну колонку.

CSS
.box {
  container-type: inline-size;
}
@container (max-width: 300px) {
  dl {
    grid-template-columns: 1fr;
  }
}

Пример: dl меняет колонки по ширине блока

Результат

Двигайте ползунок и переключайте правило: под результатом ширина блока, число колонок и ширина значения.

Длинные слова в теге dl: minmax и overflow-wrap

Длинное слово или хэш в dd растягивают колонку 1fr до своей ширины, и появляется горизонтальная прокрутка: минимальная ширина у 1fr равна самому длинному слову. Колонка minmax(0, 1fr) не растягивается, но слово выходит за её край, поэтому нужен ещё и перенос. Правило overflow-wrap: anywhere разрешает разорвать слово в любом месте и работает даже с 1fr, а overflow-wrap: break-word при 1fr не помогает: колонка уже растянута.

CSS
dd {
  overflow-wrap: anywhere;
}

Пример: длинное слово в dd

Результат

Выберите правило: рядом с каждым написано, растянулась ли колонка и вышло ли слово за край.

Прайс на теге dl: точки-заполнители между dt и dd

Точки между названием и ценой делают флексом: каждую группу записывают в div с display: flex, а dt растягивают и делают флекс-контейнером, чтобы его псевдоэлемент ::after заполнил свободное место пунктирной линией. Цена в dd остаётся справа, а длинное название переносится на следующую строку.

CSS
div {
  display: flex;
}
dt {
  display: flex;
  flex: 1;
}
dt::after {
  content: '';
  flex: 1;
  border-bottom: 2px dotted;
  margin: 0 6px;
}

Пример: прайс с точками-заполнителями

Результат

Выберите вариант: вверху правила, под результатом пояснение. Последнее название длинное, чтобы было видно перенос.

Тег dl и float: почему dd уезжает от своего dt

Раскладка через float ломается, когда название выше описания: dd следующей пары встаёт рядом с предыдущим dt, а не со своим. Даже с clear: left у dt сам dt уходит вниз под первый, а его dd остаётся наверху. Правило overflow: hidden у dd не помогает: следующее описание всё равно встаёт рядом с высоким плавающим dt. Помогает очистка внутри dd: псевдоэлемент ::after с clear: both растягивает dd на высоту названия. Проще взять grid, как в разделе про две колонки.

CSS
dt {
  float: left;
  clear: left;
  width: 100px;
}
dd {
  margin: 0 0 0 110px;
}
dd::after {
  content: '';
  display: block;
  clear: both;
}

Пример: float у dt и очистка внутри dd

Результат

Выберите вариант: под результатом число пар, где описание стоит на одной строке со своим названием.

Оформление тега dl: двоеточие, линии и зебра

Двоеточие после названия добавляет dt::after, поэтому в разметке его писать не нужно. Линию между группами рисует селектор div + div, а зебру — div:nth-child(even): обоим нужна обёртка div. Без обёртки dt:nth-of-type(even) красит только названия, потому что считает одни dt и не трогает dd. Для второго и следующих значений одного названия подходит dd + dd.

CSS
dt::after {
  content: ':';
}
div + div {
  border-top: 1px solid #ccc;
}
div:nth-child(even) {
  background: #FFF1EA;
}

Пример: двоеточие, линии и зебра

Результат

Выберите правило: вверху его код, под результатом написано, что выделилось.

Тег dl в JavaScript: собрать из данных и найти описание

Список определений собирают из массива пар: для каждой пары создают dt и dd и добавляют оба методом append. Текст записывают через textContent, чтобы символы < и & из данных не превратились в разметку.

JavaScript
dl.replaceChildren();
for (const [k, v] of data) {
  const dt = document.createElement('dt');
  dt.textContent = k;
  const dd = document.createElement('dd');
  dd.textContent = v;
  dl.append(dt, dd);
}

Пример: собрать dl из массива пар

Результат

Нажимайте кнопки: вверху выполненная команда, под списком число пар в данных и тегов в dl.

Чтобы найти описание названия, берут dt.nextElementSibling, а для нескольких описаний идут по соседям, пока встречаются dd. С обёртками div соседи dt и dd остаются теми же, но dl.children возвращает группы, а не отдельные теги: названия считают через dl.querySelectorAll('dt').

JavaScript
const dt = document.querySelector('#t');
const list = [];
let n = dt.nextElementSibling;
while (n && n.tagName === 'DD') {
  list.push(n.textContent);
  n = n.nextElementSibling;
}

Пример: найти все описания названия

Результат

Выберите команду: вверху код, под списком результат, который скрипт посчитал в этом кадре.

Атрибуты тега dl: только глобальные

У dl нет собственных атрибутов: работают только глобальные, например class, id, lang, dir и title. Устаревший атрибут compact валидатор отмечает предупреждением, а на вид списка он не влияет. Атрибуты type и nowrap у dl, dt и dd недопустимы. Роли term и definition лишние: у dt и dd такая роль уже есть. Список глобальных атрибутов приведён в стандарте WHATWG.

АтрибутСтатусЧто делаетПример записи
class, id, style, lang, dir, titleактуаленГлобальные атрибуты: работают у dl, dt и dd. Например, dir="rtl" переносит отступ у dd вправо<dl class="specs">
compactустарелКогда-то просил сжать список. Сейчас на вид не влияет, валидатор выдаёт предупреждение<dl compact>
role="term", role="definition"лишнийУ dt и dd такая роль задана самим тегом, валидатор выдаёт предупреждение<dt role="term">
type, nowrapнедопустимДля dl, dt и dd такие атрибуты не определены, валидатор считает их ошибкой<dl type="1">

Вопросы про тег dl: dt и dd в одну строку и колонки без разрыва

Два вопроса, которых нет в разделах выше: как вывести dt и dd в одну строку и как не разорвать пару в колонках.

Как вывести dt и dd в одну строку без grid?

Для этого dt и dd делают display: inline. У dd при этом остаётся горизонтальный margin-left: 40px, поэтому его обнуляют, а между парами добавляют перенос через dd::after с content: '\A' и white-space: pre. Двоеточие после названия добавляет dt::after.

CSS
dt,
dd {
  display: inline;
  margin: 0;
}
dt::after {
  content: ': ';
}
dd::after {
  content: '\A';
  white-space: pre;
}

Пример: название и значение в одну строку

Результат

Выберите вариант: под результатом расстояние между dt и dd и число строк.

Как не разорвать пару dt и dd в колонках?

При columns браузер может оставить dt внизу одной колонки, а dd перенести в следующую. Это исправляет break-after: avoid у dt или обёртка div с break-inside: avoid.

CSS
dl {
  columns: 2;
}
dt {
  break-after: avoid;
}

Пример: dl в две колонки без разрыва пары

Результат

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

Частые ошибки с тегом dl

Типичные ошибки с тегом dl и как их исправить.

ОшибкаЧто происходитКак исправить
dt без ddОшибка валидатора: у группы нет описанияЗаписать dd или убрать dt
dd раньше dtОшибка валидатора: группа начинается с dtПоменять порядок: сначала название
p, span или текст прямо в dlОшибка валидатора: допустимы только dt, dd и divЗаписать содержимое внутри dd
Две группы в одном divОшибка валидатора: div вмещает одну группуОдин div на каждую группу
Часть групп в div, часть без негоОшибка валидатора: нельзя смешиватьОбернуть все группы или ни одной
h3 внутри dtОшибка валидатора: заголовок в dt запрещёнЗаписать название текстом или в strong
dl внутри pБраузер закрывает абзац, остаётся пустой pЗаписать dl рядом с абзацем
dl прямо в ul или внутри dlОшибка валидатораЗаписать внутри li или внутри dd
Пары «название и значение» через div и bНазвание и значение ничем не связаныЗаписать их как dt и dd
Grid с двумя dd без grid-columnВторой dd в колонке названий, следующий dt сдвинулсяЗадать dt первую колонку, dd вторую
Колонка 1fr и длинное слово в ddКолонка растянулась, появилась горизонтальная прокруткаКолонка minmax(0, 1fr) и overflow-wrap: anywhere
float у dt при высоком названииdd встаёт рядом с чужим dtИспользовать grid или очистку в dd::after
dt:nth-of-type(even) для зебрыЗакрашены только названияОбернуть группы в div и взять div:nth-child(even)
role="term" у dtПредупреждение валидатора: роль лишняяУбрать role
Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×