Семантика та структура пар імен-значення


77

Це питання, з яким я боровся якийсь час. Який правильний спосіб розмітити пари імена / значення?

Мені подобається елемент <dl>, але він створює проблему: немає можливості відокремити одну пару від іншої - у них немає унікального контейнера. Візуально код не має визначення. Однак семантично я думаю, що це правильна розмітка.

<dl>
    <dt>Name</dt>
    <dd>Value</dd>
    <dt>Name</dt>
    <dd>Value</dd>
</dl>

У наведеному вище коді важко візуально правильно компенсувати пари, як у коді, так і в отриманні. Якби я хотів, наприклад, але межу навколо кожної пари, це було б проблемою.

Ми можемо вказати на таблиці. Можна стверджувати, що пари імені-значення є табличними даними. Мені це здається неправильним, але я бачу аргумент. Однак HTML не диференціює ім'я від значення, крім позиції або додавання назв класів.

<table>
    <tr>
        <td>Name</td>
        <td>Value</td>
    </tr>
    <tr>
        <td>Name</td>
        <td>Value</td>
    </tr>
</table>

Це має набагато більше сенсу з візуальної точки зору як у коді, так і в CSS. Стилізація вищезгаданого кордону є тривіальною. Однак, як зазначалося вище, семантика в кращому випадку нечітка.

Думки, коментарі, запитання?

Редагувати / оновлювати Можливо, це було те, про що я повинен був би прямо згадати стосовно структури, але список визначень також має проблему несемантичного групування пар. Впорядкованість та неявний кордон між a ddта a dtлегко зрозуміти, але вони все одно відчувають для мене трохи відверте.


Re: ваше редагування / оновлення - якщо ви хотіли абсолютно впевнитись у відсутності двозначності щодо семантичних взаємозв’язків між вузлами, ви завжди могли б отримати дуже детальний розпис і зробити <dt id = "key1"> Ім'я </dt> <dd about = "# key1 "> Значення 1 </dd> <dd about =" # key1 "> Значення 2 </dd>, але деякі називають це надмірним. ;)
люцидер

Ви також повинні запитати про CSS. Наприклад, це <dl>було б не так вже й погано, але важко стилізувати відображення пар в рядку (як у таблиці)
Тейхін

Було багато хороших відповідей, особливо з боку коду, але я все ще трохи вагаюся щодо майже всіх з них. Це лише тому, що кожне рішення - це давання і прийняття. Незабаром я позначу одну з поточних відповідей як найкращу для цієї теми, але знайте, що це жорстке рішення.
Райан Кінал

@Danny Lin's був єдиним! Семантика та стиль із легкістю завдяки вдосконаленим характеристикам! stackoverflow.com/a/50313363/792888
EvilDr

Відповіді:


57

Дякую за це цікаве запитання. Тут слід розглянути ще кілька речей.

Що таке пара? Два елементи разом. Тож нам потрібен тег для цього. Скажімо, це pairтег.

 <pair></pair>

Пара містить ключ і відповідне значення:

 <pair><key>keyname</key><value>value</value></pair>

Потім нам потрібно перерахувати пари:

<pairlist>
     <pair><key>keyname</key><value>value</value></pair>
     <pair><key>keyname</key><value>value</value></pair>
</pairlist>

Наступне, що слід врахувати, це показ пар. Звичайний макет - табличний:

key value
key value

та необов’язковий роздільник, яким зазвичай є двокрапка:

key : value
key : value

Двокрапки можна легко додати за допомогою CSS, але це точно не буде працювати в IE.

Описаний вище випадок є ідеальним. Але немає дійсної розмітки HTML, яка б легко вписалась у це.


Підсумовуючи:

dlє семантично найближчим для простих випадків ключа та значення, але важко застосувати візуальні стилі (наприклад, відобразити пари в рядку або додати червону межу до щойно наведеної пари). Справа, яка найбільше підходить, - dlце глосарій. Але це не той випадок, який ми обговорюємо.

Єдиною альтернативою, яку я бачу в цьому випадку, є використання table, наприклад:

<table summary="This are the key and value pairs">
    <caption>Some notes about semantics</caption>
    <thead class="aural if not needed">
        <tr><th scope="col">keys</th><th scope="col">values</th></tr>
    </thead>
    <tbody class="group1">  
        <tr><th scope="row">key1</th><td>value1</td></tr>
        <tr><th scope="row">key2</th><td>value2</td></tr>
    </tbody>
    <tbody class="group2">
        <tr><th scope="row">key3</th><td>value3</td></tr>
        <tr><th scope="row">key4</th><td>value4</td></tr>
    </tbody>
</table>

Ще один:

<ul>
  <li><strong>key</strong> value</li>
  <li><strong>key</strong> value</li>
</ul>

або:

<ul>
  <li><b>key</b> value</li>
  <li><b>key</b> value</li>
</ul>

або, коли ключі можуть бути пов’язані:

<ul>
  <li><a href="/key1">key1</a> value</li>
  <li><a href="/key2">key1</a> value</li>
</ul>

Пари ключів і значень зазвичай зберігаються в базі даних, а ті, як правило, зберігають табличні дані, тому таблиця найкраще підходить для IMHO.

Як ти гадаєш?


4
Дуже ґрунтовна відповідь. Мені подобається, як ти показав свою думку. +1
Райан Кінал

а як щодо приблизно такого: хоч <ul> <li><div class="key">key</div><div class="value">value</div></li> </ul>ми можемо мати довільні ключі та значення (значенням може бути інший список, зображення тощо)
Енріке

також, для рішення таблиці, можливо, ви могли б використовувати <col class="key"/>тег. У будь-якому випадку, я думаю, що рішення таблиці не є добрим, що станеться, якщо ми зможемо показати ключ і значення в різних рядках?
Енріке,

2
Я вважаю (ну, майже знаю ) <strong>слід замінити <b>відповідно до семантики HTML5.
Andreas Rejbrand

1
Це питання є головним у Google. Не могли б ви оновити свою відповідь, щоб відобразити вказівки @Danny Lin щодо використання divs в межах dl? Це вирішує проблему семантики і стилю, що дозволяє уникнути шуму <b>і <strong>: stackoverflow.com/a/50313363/792888
EvilDr

21

Після специфікаціїдодаткову інформацію ) , представлену Олександр Антонов: використання dl, dt, ddі, по виборуdiv .

Комбінація dl, dtі ddсемантично відмінно підходить для пар ключ-значення:

<dl>
    <dt>Key1</dt>
    <dd>Value1</dd>
    <dt>Key2</dt>
    <dd>Value2</dd>
</dl>

Для полегшення стилізації та синтаксичного аналізу divs можна використовувати як дочірні групи dlдля групування пар ключ-значення (а також створює dtта ddє онуками dl):

dl { display: table; }
dl > div { display: table-row; }
dl > div > dt, dl > div > dd { display: table-cell; border: 1px solid black; padding: 0.25em; }
dl > div > dt { font-weight: bold; }
<dl>
  <div>
    <dt>Key1</dt>
    <dd>Value1</dd>
  </div>
  <div>
    <dt>Key2</dt>
    <dd>Value2</dd>
  </div>
</dl>


Відмінна відповідь, і IMHO має бути прийнятою відповіддю, особливо враховуючи приклад, включений до специфікації, який ідеально відповідає цьому питанню. CSS Grid також буде досить дивовижним способом простого та ефективного форматування.
EvilDr

12

XHTML 2 представляє можливість групування термінів та визначень за допомогою diелемента

<!-- Do not us this code! -->
<dl>
    <di>
        <dt>Name</dt>
        <dd>John</dd>
    </di>
    <di>
        <dt>Age</dt>
        <dd>25</dd>
    </di>
</dl>

X / HTML 5 проти XHTML 2> Покращення до списків визначень

На жаль, XHTML 2 мертвий, а HTML5 не має diелемента

Отже, ви можете поєднувати ul > liз dl > dt + dd:

<ul>    
    <li>
        <dl>
            <dt>Name</dt>
            <dd>John</dd>
        </dl>
    </li>
    <li>
        <dl>
            <dt>Age</dt>
            <dd>25</dd>
        </dl>
    </li>
</ul>

7
О чоловіче. Ого. Я хочу <di>стихію. Я хочу це зараз. Шкода, що я цього не можу мати. Дякую за інформацію!
Ryan Kinal

2
Відповідно до специфікації, divбере на себе роль di. Дивіться мою відповідь для деталей.
Денні Лін

6

Я думаю, що перелік визначень - це, мабуть, погана ідея. Семантично вони використовуються для означень. Інші списки ключ-значення часто відрізнятимуться від назв та описів визначень.

A table- один із шляхів, але як щодо невпорядкованого списку?

<ul>
    <li class="key-value-pair">
        <span class="key">foo</span>
        <span class="value">bar</span>
    </li>
</ul>

2
Списки визначень можуть бути дещо погано названі в цьому відношенні, але вони призначені не лише для визначень (якби вони були б досить обмеженими) - специфікація W3C. що визначає їх, насправді має приклад використання їх для розмітки діалогу.
lucideer

Думаючи про це з об'єктно-орієнтованої точки зору, я припускаю, що я шукаю "невпорядкований список пар імен-значень", але я не впевнений, що це найкраща відповідь (на даний момент). +1
Райан Кінал

1
Це свого роду підхід до мікроформатів, але у візуалізації браузера за замовчуванням або в програмі зчитування з екрану ви отримаєте foo bar, як foo barвзагалі без будь-яких тегів. Один з прольотів повинен бути більше, ніж проліт. Може бути <strong>? Тоді другий не потрібен.
Тейхін

3
У поточній специфікації HTML5 dl було перейменовано як список опису, що робить його використання тут більш правильним.
Ерік Бок,

3

Це не моє вподобане рішення, але це розумне зловживання семантичним елементом:

Використовуйте нову <dl>для <dt>/ <dd>пари:

<div class="terms">
    <dl><dt>Name 1</dt><dd>Value 1</dd></dl>
    <dl><dt>Name 2</dt><dd>Value 2</dd></dl>
</div>

Приклад із css-плаваючими та червоними рамками при наведенні:

dt:after { content:":"; }
dt, dd { float: left; }
dd { margin-left: 5px }
dl { float: left; margin-left: 20px; border: 1px dashed transparent; }
dl:hover { border-color: red; }
<div class="terms">
    <dl>
        <dt>Name 1</dt>
        <dd>Value 1</dd>
    </dl><!-- etc -->
    <dl><dt>Name 2</dt><dd>Value 2</dd></dl>
    <dl><dt>Name 3</dt><dd>Value 3</dd></dl>
    <dl><dt>Name 4</dt><dd>Value 4</dd></dl>
    <dl><dt>Name 5</dt><dd>Value 5</dd></dl>
    <dl><dt>Name 6</dt><dd>Value 6</dd></dl>
</div>


Цікаво. Це могло б спрацювати, якщо б не потрібно було складати перелік пов’язаних предметів ... хоча, я гадаю, один МОЖЕ інкапсулювати кожен <dl>у<li>
Armstrongest


2

важко візуально правильно компенсувати пари, як у коді, так і в отриманні. Якби я хотів, наприклад, але межу навколо кожної пари, це було б проблемою.

Інші до мене мали справу (досить добре, на мою думку) з проблемою надання візуального визначення в коді. Що залишає проблему візуалізації та CSS. У більшості випадків це можна зробити досить ефективно. Найбільшим винятком є ​​розміщення рамки навколо кожного набору dt / dds, що, правда, надзвичайно складно - можливо, неможливо надійно оформити стиль.

Ви можете зробити:

dt,dd{ border:solid; }
dt{ margin:10px 0 0 0; border-width:1px 1px 0 1px; }
dd{ margin:0 0 10px 0; border-width:0 1px 1px 1px; padding:0 0 0 10px; }
dd::before{ content:'→ '; }

Що працює для пар ключ-значення, але створює проблеми, якщо у вас є кілька ідентифікаторів в одному "наборі", наприклад:

<dt>Key1</dt>
  <dd>Val1.1</dd>
  <dd>Val1.2</dd>
<dt>Key2</dt>
  <dd>Val2.1</dd>
  <dd>Val2.2</dd>

Однак, якщо не брати до уваги обмеження стилю меж, робити будь-що інше для асоціювання наборів (фони, нумерація тощо) з CSS цілком можливо. Тут є приємний огляд: http://www.maxdesign.com.au/articles/definition/


Ще один момент, який, на мою думку, варто зауважити, якщо ви хочете оптимально стилізувати списки визначень, щоб забезпечити візуальне розділення - функції автоматичної нумерації CSS ( counter-incrementі counter-reset) можуть бути дуже до речі: http://www.w3.org/TR/ CSS2 /gene.html # лічильники


2

Звичайно, ви можете просто використовувати елементи HTML Custom . ( специфікація ) Це цілком дійсний HTML5.

На жаль, підтримка браузера не така вже й велика, але якщо рідко ми маємо справу з такими пішохідними речами, як підтримка браузера, коли маємо справу з семантикою. :-)

Одним із таких способів ви можете це представити:

Після реєстрації вашого абсолютно нового вигадливого елемента:

var XKey = document.registerElement('x-key');
document.body.appendChild(new XKey());

Ви пишете розмітку так:

<ul>
  <li>
    <x-key>Name</x-key>
    Value
  </li>
</ul>

Єдина умова, яку мають користувацькі елементи HTML, полягає в тому, що вони потребують тире в них. Звичайно, тепер ви можете бути супер креативними ... якщо ви будуєте склад автозапчастин зі списками деталей та серійними номерами:

<ul>
  <li>
    <auto-part>
      <serial-number>AQ12345</serial-number>
      <short-description>lorem ipsum dolor...</short-description>
      <list-price>14</list-price>
    </auto-part>
  </li>
</ul>

Ви не можете отримати набагато більше семантики, ніж це!

Однак є шанс, що я зайшов занадто далеко semantic-shangri-la-la(справжнє місце), і, можливо, я маю спокусу повернути його до чогось більш загального:

<ul>
  <li class='auto-part' data-serial-number="AQ12345">
      <p class='short-description'>lorem ipsum dolor...</p>
      <p class='list-price'>14</p>
  </li>
</ul>

Або, можливо, це (якщо мені потрібно було оформити і наочно показати ключ)

<ul>
  <li class='auto-part'>
      <x-key>AQ12345<//x-key>
      <p class='short-description'>lorem ipsum dolor...</p>
      <p class='list-price'>14</p>
  </li>
</ul>

Дуже цікаво. Я можу розглянути це наступного разу, коли мені знадобляться пари.
Райан Кінал

1

Хм dt/ ddЗвук краще для цього і є можливість їх зміщення візуально, хоча я згоден , що це набагато складніше , ніж за столом.

Що стосується читабельності вихідного коду, то як щодо їх розміщення в один рядок?

<dl>
    <dt>Name</dt> <dd>Value</dd>
    <dt>Name</dt> <dd>Value</dd>
</dl>

Я згоден, що це не на 100% ідеально, але, оскільки ви можете використовувати пробіли для відступу:

<dl>
    <dt>Property with a looooooooooong name</dt>   <dd>Value</dd>
    <dt>Property with a shrt name</dt>             <dd>Value</dd>
</dl>

це може бути найкращий спосіб.


Проблема полягає в тому, що згідно специфікації, dtможе мати більше одного, ddякий може бути або не бути бажаним.
Armstrongest

1

За винятком <dl>елемента, ви майже підсумували всі варіанти HTML: обмежені.

Однак ви не загублені, залишився один варіант: використання мови розмітки, яку можна перекласти в HTML. Дуже хороший варіант - Markdown.

Використовуючи розширення таблиці, яке надають деякі двигуни націнки, ви можете мати такий код:

| Table header 1 | Table header 2 |
-----------------------------------
| some key       | some value     |
| another key    | another value  |

Це означає, що вам потрібен крок побудови, щоб перекласти Markdown в HTML, звичайно.

Таким чином ви отримуєте значущу розмітку (таблицю для табличних даних) та код, який можна обслуговувати.


1
Отже, ви знову отримаєте стіл, але до нього більше праці. Здається, це взагалі не вирішує жодних проблем.
pydsigner

0

Як щодо просто розміщення порожнього рядка між кожною парою?

Це не вимагає спеціальної обробки довгих значень.

<dl> 
    <dt>Name</dt> 
    <dd>Value</dd> 

    <dt>Name</dt> 
    <dd>Value</dd> 

    <dt>Name</dt> 
    <dd>Value</dd> 
</dl> 

Пробіли не мають семантичного значення в HTML. 1 простір або кілька пробілів, повернення каретки CR, tabі переклад рядка по LFсуті , все перевести в простір. Можливо, це більш привабливо для людини, що читає код, але не надає жодного семантичного значення.
Armstrongest

0

А як щодо використання списків?

Замовлено:

<ol>
  <li title="key" value="index">value</li></ol>

Або використовуйте <ul>для невпорядкованого списку та пропустіть value="index"біт.


0

Рядок із специфікації :

Групи імен-цінностей можуть бути термінами та визначеннями, темами та значеннями метаданих, питаннями та відповідями або будь-якими іншими групами даних імен-значення .

Я припускаю використання елементів <dl>, <dt>і <dd>.


2
Дякуємо за посилання на специфікацію. Так, специфікація дозволяє парами ім’я-значення, але dlелемент може бути проблематично відображати візуально, оскільки для кожної key/ valueпари немає контейнера . Його первісне використання, ймовірно, було для переліку елементів глосарію чи словникових статей, які мають 1 термін та кілька визначень.
Армстронгест

-1

Мені подобається ідея Unicron розмістити їх усіх в одному рядку, але іншим варіантом буде відступ до значення під назвою визначення:

<dl>
    <dt>Name</dt>
       <dd>Value</dd>
    <dt>Name</dt>
       <dd>Value</dd>
</dl>

Цей спосіб може бути трохи простішим для очей у смішно довгих визначеннях (хоча, якщо ви використовуєте смішно неправильні визначення, то, можливо, перелік визначень не є тим, що ви насправді хочете).

Що стосується візуалізації на екрані, то дефіцит нижнього жиру, застосований до dd, є великим візуальним розділенням.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.