Semantics and Structure of Name-Value Pairs
Asked Answered
M

14

96

This is a question I have been struggling with for a while. What is the proper way to mark up name/value pairs?

I'm fond of the <dl> element, but it presents a problem: There is no way to separate one pair from another - they have no unique container. Visually, the code lacks definition. Semantically, though, I think this is the correct markup.

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

In the above code, it is difficult to properly offset the pairs visually, both in code and rendered. If I wanted to, for instance, but a border around each pair, that would be a problem.

We may point to tables. It could be argued that name-value pairs are tabular data. That seems incorrect to me, but I see the argument. However, the HTML does not differentiate the name from the value, except in position, or with the addition of class names.

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

This makes much more sense from a visual standpoint, both in code and in CSS. Styling the aforementioned border is trivial. However, as mentioned above, the semantics are fuzzy at best.

Thoughts, comments, questions?

Edit/Update Perhaps this was something I should have explicitly mentioned in relation to structure, but a definition list also has the problem of not semantically grouping the pairs. The ordering and implicit border between a dd and a dt is easily understood, but they still feel slightly off to me.

Moil answered 19/7, 2010 at 12:40 Comment(4)
Re: your edit/update - if you wanted to ensure absolutely that there's no ambiguity about the semantic relationships between nodes you could always get really verbose and do <dt id="key1">Name</dt><dd about="#key1">Value 1</dd><dd about="#key1">Value 2</dd> but some would call that overkill. ;)Emit
You should also ask about the CSS. E.g. <dl> would be not so bad, but it is hard to style to display the pairs inline (like in table)Shay
There have been many good answers, especially on the code side, but I'm still slightly hesitant about nearly all of them. This is only because every solution is a give-and-take. I will be marking one of the current answers as best for this thread soon, but know that it's a tough decision.Moil
@Danny Lin's was the one! Semantics and style with ease thanks to the improved spec! https://mcmap.net/q/218136/-semantics-and-structure-of-name-value-pairsVilma
S
69

Thanks for this interesting question. There are few more things to consider here.

What is a pair? Two elements together. So we need a tag for this. Let's say it is pair tag.

 <pair></pair>

The pair contains the key, and the corresponding value:

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

Then, we need to list the pairs:

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

The next thing to consider, is the display of the pairs. The usual layout is the tabular one:

key value
key value

and the optional separator, which is usually colon:

key : value
key : value

The colons can be easily added via CSS, but this certainly won't work in IE.

Case described above is the ideal one. But there is no valid HTML markup to fit in this easily.


To sum up:

dl is semantically closest, for simple cases of key and value, but is hard to apply visual styles (eg. to display the pairs inline or to add red border to just hovered pair). The case which fits most for dl is glossary. But this is not the case we discuss.

The only alternative I can see in this case is to use table, like this:

<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>

One more:

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

or:

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

or, when the keys may be linked:

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

The key and value pairs are usually stored in database, and those usually store tabular data, so the table would fit best IMHO.

What do you think?

Shay answered 19/7, 2010 at 19:43 Comment(6)
Very thorough answer. I like how you showed your line of thought. +1Moil
and what about something like this: <ul> <li><div class="key">key</div><div class="value">value</div></li> </ul> whit that we can have arbitrary keys and values (a value could be another list, an image, etc.)Januaryjanuisz
also, for the table solution maybe you could use the <col class="key"/> tag. Anyway, I think the table solution is not good, what happens if we can show the key and the value in different lines?Januaryjanuisz
The verbosity of the table solution suggests against it's use, but an unordered list is pretty good.Penitence
I believe (well, almost know) <strong> should be replaced by <b> according to the HTML5 semantics.Pettway
This question is tops in Google. Could you please consider updating your answer to reflect @Danny Lin's input regarding the use of divs within dl? This solves the problem of semantics and styling, thus avoiding the noise of <b> and <strong>: https://mcmap.net/q/218136/-semantics-and-structure-of-name-value-pairsVilma
C
50

Following the specification (and further details) provided by Alexandr Antonov: use dl, dt, dd, and optionally div.

A combination of dl, dt, and dd is semantically fine for key-value pairs:

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

For easier styling or parsing, divs can be used as children of dl to group the key-value pairs (and makes dt and dd be grandchildren of 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>
Catania answered 13/5, 2018 at 6:26 Comment(1)
Excellent answer, and IMHO should be accepted answer, especially given the example included in the spec that fits this question perfectly. CSS Grid would also be a rather amazing way to format this simply and effectively.Vilma
D
13

XHTML 2 introduces the ability to group terms and definitions using the di element

<!-- 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 vs XHTML 2 > Enhancement To Definitions Lists

Unfortunately though, XHTML 2 is dead and HTML5 doesn't have di element

So, you can combine ul > li with 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>
Desuetude answered 27/2, 2013 at 17:50 Comment(2)
Oh man. Wow. I want the <di> element. I want it now. Too bad I can't have it. Thanks for the info, though!Moil
According to spec, div takes the role of di. See my answer for detail.Catania
M
8

dl {
  display: grid;
  grid-template-columns: auto auto;
}

dd {
  margin: 0
}
<dl>
  <dt>key</dt>
  <dd>value</dd>
  <dt>key</dt>
  <dd>value</dd>
</dl>

I used <dl> <dt> <dd> and styled them with grid

Malpighiaceous answered 29/9, 2018 at 20:16 Comment(1)
This is the most up-to-date solution. If you need to select/style name-value pairs, you can further wrap each pair in a div (Danny Lin's answer) with display: contents. That way it doesn't mess with the grid.Gagliardi
K
6

I think a definition list is probably a bad idea. Semantically, they are used for definitions. Other key-value lists will often differ from definition titles and descriptions.

A table is one way to go, but what about an unordered list?

<ul>
    <li class="key-value-pair">
        <span class="key">foo</span>
        <span class="value">bar</span>
    </li>
</ul>
Kith answered 19/7, 2010 at 12:54 Comment(4)
Definition lists may be slightly poorly named in this regard, but they are not intended purely for definitions (they would be of fairly limited use case if they were) - the W3C spec. that defines them actually has an example of using them for marking up a dialogue.Emit
Thinking about it from an object-oriented standpoint, I suppose what I'm looking for is "an unordered list of name-value pairs", but I'm not sure this is the best answer (for now). +1Moil
This is kind of microformat approach, but in default browser rendering or screen reader, you will get foo bar, like foo bar without any tags at all. One of the spans needs to be more than a span. Maybe <strong>? Then the second one is not needed.Shay
In the current HTML5 spec, dl has been rebranded as a description list which makes its use here seem more correct.Dalt
T
3

This is not my preferred solution, but it is a clever abuse of the semantic element:

Use a new <dl> per <dt>/<dd> pair:

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

An example with css floats and red border on hover:

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>
Trouper answered 27/6, 2013 at 21:31 Comment(1)
Interesting. This would would work if it's not needed to be a list of related items... though I suppose one COULD encapsulate each <dl> in an <li>Dejesus
D
3

Of course, you could just use HTML Custom elements. ( spec )They're completely valid HTML5.

Unfortunately, browser support isn't that great, but if rarely do we care about such pedestrian things as browser support when we're dealing with semantics. :-)

One such way you could represent it:

After registering your brand new fancy element like so:

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

You write markup like so:

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

The only condition that HTML Custom elements have are that they need a dash in them. Of course, you can now be super creative... if you're building an auto parts warehouse, with lists of parts and serial numbers:

<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>

You can't get much more semantic than that!

However, there IS a chance I have gone too far into semantic-shangri-la-la (a real place) and might be tempted to scale it back to something a little more generic:

<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>

Or perhaps this ( if I needed to style and show the key visually )

<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>
Dejesus answered 25/7, 2016 at 17:42 Comment(1)
Very interesting. I may look into this next time I'm in need of pairs.Moil
E
2

it is difficult to properly offset the pairs visually, both in code and rendered. If I wanted to, for instance, but a border around each pair, that would be a problem.

Others before me have dealt (quite well I think) with the problem of providing visual definition in code. Which leaves the problem of rendering and CSS. This can be done quite effectively in most cases. The biggest exception is placing a border around each set of dt/dds, which is admittedly extremely tricky - perhaps impossible to style reliably.

You could do:

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:'→ '; }

Which works for key-value PAIRS, but presents problems if you have multiple dds within one "set" like:

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

However, border-styling limitations aside, doing anything else to associate sets (backgrounds, numbering, etc.) is quite possible with CSS. There's a nice overview here: http://www.maxdesign.com.au/articles/definition/


Another point I think is worth noting, if you're looking to optimally style definition-lists to provide visual separation - CSS's automatic-numbering features (counter-increment and counter-reset) can come in quite handy: http://www.w3.org/TR/CSS2/generate.html#counters

Emit answered 19/7, 2010 at 13:16 Comment(0)
U
1

Hmm. dt/dd sound best for this and it is possible to offset them visually, although I do agree it's more difficult than for a table.

As for source code readability, how about putting them into one line?

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

I agree it's not 100% perfect, but seeing as you can use space characters for indentation:

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

it might be the nicest way.

Urinalysis answered 19/7, 2010 at 12:43 Comment(1)
The problem is that under the spec, a dt can have more than one dd which may or may not be what is desired.Dejesus
N
1

Except for the <dl> element, you've pretty much summed up all the options of HTML: limited ones.

However you're not lost, there is one option left: using a markup language that can be translated to HTML. A very good option is Markdown.

Using a table extension that some markdown engines provide, you can have code like this:

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

This means that you need a build step to translate the Markdown to HTML of course.

This way you get meaningful markup (table for tabular data) and maintainable code.

Nanette answered 31/5, 2013 at 19:30 Comment(1)
So you end up with a table again, but it's more work to get there. This doesn't seem like it solves any problems at all.Maximilianus
A
0

How about just placing a blank line between each pair?

This requires no special handling for long values.

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

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

    <dt>Name</dt> 
    <dd>Value</dd> 
</dl> 
Abib answered 19/7, 2010 at 12:59 Comment(1)
White space characters don't have any semantic meaning in HTML. 1 space or multiple spaces, carriage returns CR, tab, and Line Feeds LF essentially all translate to a space. It's perhaps more visually appealing to a human reading the code, but it doesn't impart any semantic meaning.Dejesus
P
0

What about using lists?

Ordered:

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

Or use <ul> for an unordered list, and skip the value="index" bit.

Phox answered 14/2, 2013 at 6:39 Comment(0)
E
0

The line from spec:

Name-value groups may be terms and definitions, metadata topics and values, questions and answers, or any other groups of name-value data.

I assume use of elements <dl>, <dt> and <dd>.

Eggert answered 25/7, 2016 at 16:43 Comment(1)
Thanks for linking to the spec. Yes, the spec does allow for name-value pairs, but the dl element can be troublesome to display visually, as there is no container for each key/value pair. Its original use was likely for listing out glossary items or dictionary entries, which have 1 term and multiple definitions.Dejesus
B
-1

I do like Unicron's idea of putting them all on one line, but another option would be to indent the value below the definition name:

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

This way might be a little easier on the eye in ridiculously long definitions (although if you're using ridiculously wrong definitions then perhaps a definition list isn't what you really want after all).

As for the rendering on screen, a fat bottom margin applied to the dd is plenty visual separation.

Blackett answered 19/7, 2010 at 12:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.