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.
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>key1 value</li>
<li>key1 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?
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>
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>
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>
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
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>
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
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>
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.
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.
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>
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.
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>.
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.
Related
Can we use a different <dl> for each <dt>, <dd> pairs? Will there be any problems with accessibility if we do it? Use-case being to simplify some Component API. For example:
<!-- Can we do this -->
<div class="container">
<dl>
<dt>First Name</dt>
<dd>Jeff</dd>
</dl>
<dl>
<dt>Last Name</dt>
<dd>Bezos</dd>
</dl>
</div>
<!-- instead of this? -->
<div class="container">
<dl>
<dt>First Name</dt>
<dd>Jeff</dd>
<dt>Last Name</dt>
<dd>Bezos</dd>
</dl>
</div>
In this case, it doesn't matter because definition lists suck in general for accessibility purposes. See my (editorial) comment in this answer, How to properly use aria selectors for definition lists in puppeteer
A definition list does not have a "list" role by default so different screen readers interpret them differently. Because of this, whether you have separate <dl>s or not won't have a huge impact.
"Real" lists, <ul> and <ol>, do make a difference. If you have a group of things that are related and are contained in one list, then it should only be one <ul> rather than a series of <ul>s. A screen reader conveys metadata information about lists such as the number of elements in the list. You get that information "for free" with your eyes if you're sighted. You can generally tell how many items are in a list (if it's not too long) whereas a screen reader user doesn't have that "seeing" option so the screen reader can tell them it's a list with 5 items, but only if it's a single <ul> with 5 <li> elements.
Given a definition list such as
<dl>
<dt>first term</dt>
<dd>first term definition</dd>
<dt>second term</dt>
<dd>second term definition</dd>
<dt>the third term</dt>
<dd>third term definition</dd>
</dl>
I would like each term and it's definition to behave like a block, i.e. the definition should appear alongside the corresponding term like so
first term first term definition
second term second term definition
the third term third term definition
One way to achieve this would be to wrap each <dt> and <dd> pair in a <div> add add a rule
dt, dd {
display: inline
}
But ideally I'd like to achieve this without adding any additional elements.
I'd also like the definitions to be left-aligned (as shown above) no matter how long each of the terms are, i.e. without using something like margin-left: 50px on the definitions.
I can't honestly recommend this as it may have unknown aspects by changing the natural display of the elements but CSS-Grid can do that.
dl {
display: inline-grid;
}
dt {
grid-column: 1
}
dd {
grid-column: 2;
}
<dl>
<dt>first term</dt>
<dd>first term definition</dd>
<dt>second term</dt>
<dd>second term definition</dd>
<dt>the third term</dt>
<dd>third term definition</dd>
</dl>
I want to make an ordered definition list. Should I nest an <ol> in a <dl>, or the other way around?
i.e.
<h4>Bike Descriptions</h4>
<dl>
<ol>
<li>
<dt>Giant Bikes</dt>
<dd>Bikes that are very sturdy and reliable.</dd>
</li>
<li>
<dt>Walmart Bikes</dt>
<dd>Bikes that are crummy and heavy.</dd>
</li>
</ol>
</dl>
Or nest the <dl> within <ol> or even within each <li>?
The docs don't seem to say.
According to that documentation, the only elements a <dl> may contain are <dt> and <dd>:
Content model:
Zero or more groups each consisting of one or more dt elements followed by one or more dd elements, optionally intermixed with script-supporting elements.
Thus, your example code is invalid HTML. The only valid way to nest dl and ol/ul is in the order ol/ul > li > dl > dt+dd:
<h4>Bike Descriptions</h4>
<ol>
<li>
<dl>
<dt>Giant Bikes</dt>
<dd>Bikes that are very sturdy and reliable.</dd>
</dl>
</li>
<li>
<dl>
<dt>Walmart Bikes</dt>
<dd>Bikes that are crummy and heavy.</dd>
</dl>
</li>
</ol>
Your example is not a valid HTML tag. Perhaps you would like to do something like this.
<h4>Bike Descriptions</h4>
<ul>
<li>
<dl>
<dt>Giant Bikes</dt>
<dd>Bikes that are very sturdy and reliable.</dd>
</dl>
</li>
<li>
<dl>
<dt>Walmart Bikes</dt>
<dd>Bikes that are crummy and heavy.</dd>
</dl>
</li>
</ul>
Then you can add style to your CSS to fix the layout.
I don't think HTML has an element for an ordered definition list.
You might consider just using a dl element and then ordering its name-value groups how you'd like. (For example, the words in a dictionary typically aren't numbered and are just alphabetically ordered.)
If you really think you must number each name-value group of a dl element, then I think I'd likely disagree with you and beg you to reconsider, since I can't think of any examples where I'd consider doing so to be good style. If you can, feel free to share. But I tend to like to keep it simple, stupid (KISS); I think less is often more; and probably you aren't gonna need it (YAGNI). However, if (even after reconsidering) you still want to do it, then you might consider using CSS counters.
According to WHATWG: HTML Standard: The dl element:
The order of the list of groups, and of the names and values within each group, may be significant.
In order to annotate groups with microdata attributes, or other global attributes that apply to whole groups, or just for styling purposes, each group in a dl element can be wrapped in a div element. This does not change the semantics of the dl element.
HTML doesn't have a way to markup an ordered definition list. I would suggest using a regular <li>, and the term defined marked with a <dfn> tag:
<ul>
<li><dfn>Giant Bike</dfn> Bikes that are very sturdy and reliable.</li>
<li><dfn>Walmart Bikes</dfn> Bikes that are crummy and heavy.</li>
</ul>
According to the HTML spec, a <dl> already accounts for ordering being important to some extend:
The order of the list of groups, and of the names and values within each group, may be significant.
Also, from your example I don't thing order is the most important thing (i.e. it's not a step by step guide or anything like that).
In any case, if you think it is, I would suggest you use a regular <ol> and the <dfn> tag:
The <dfn> HTML element is used to indicate the term being defined within the context of a definition phrase or sentence. The <p> element, the <dt>/<dd> pairing, or the <section> element which is the nearest ancestor of the <dfn> is considered to be the definition of the term.
According to this, I think the best way to represent an ordered list of definitions is like so:
dfn {
display: block;
margin-bottom: 8px;
font-weight: bold;
font-style: normal;
}
<h4>Bike Descriptions</h4>
<ol>
<li>
<p>
<dfn>Giant Bikes</dfn>
Bikes that are very sturdy and reliable.
</p>
</li>
<li>
<p>
<dfn>Walmart Bikes</dfn>
Bikes that are crummy and heavy.
</p>
</li>
</ol>
Let's say I have the following layout on some pages:
Title: Some Title
Author: Some Author
Author Date of Birth: Date of birth
Notes:
Left side text is right-aligned and bold.
Used on several different pages.
The right side can contain input controls at some point.
What would be the most appropriate method to apply in this situation? I can think of a few options (assume CSS applied in external style sheet):
Table
Simple, easy, but I'm not sure this would be considered a good use of tables.
<table>
<tr>
<td>Title</td>
<td>Some Title</td>
</tr>
</table>
Div + Classes
I feel like this is a case of divitis and classitis rolled into one.
<div class="information">
<div class="title">Title</div><div class="value">Some Title</div>
</div>
Container Div
This feels more like the right path but I'm not sure.
<div class="information">
<strong>Title</strong> <span>Some Title</span>
</div>
Suggestions?
I think a good semantic choice here is the dl (description list) element.
http://developers.whatwg.org/grouping-content.html#the-dl-element
<dl>
<dt>Title</dt>
<dd>Some Title</dd>
<dt>Author</dt>
<dd>Some Author</dd>
<dt>Author Date of Birth</dt>
<dd>Date of birth</dd>
</dl>
Use a table, this is one of the few instances where using a table actually isn
't all that wrong. You're not using it for layout but text markup.
Then apply a class to every first column and in css make that class have text-align: right; which applies to that column.
I think you're right in you saying you want to use a table, but don't want to use. In this case i don't think a table is correct either. I personally only use tables if i need to organize data nicely. Because you have so much, a bunch of floated divs everywhere is more of a hassle then just using a table.
Because this is only two columns I would say use use two divs with floats or use two spans, instead of strong use a span and then style it with css.
This is clearly a good example of when to use tables.
It's tabular data.
Use ths for the first columns cells to be able to style it.
I even think ths are bold by default. Not sure about all browsers though so wouldn't hurt to style them bold to be sure :).
A table is a means of arranging data in rows and columns.
And this is what you are doing.
Definition list would be semantically correct.
<dl>
<dt>Title:</dt>
<dd>Some Title<dd>
<dt>Author:</dt>
<dd>Some Author</dd>
<dt>Author Date of Birth:</dt>
<dd>Date of birth</dd>
</dl>
See W3C for more details - http://www.w3schools.com/tags/tag_dl.asp
Should I still be using tables anyway?
The table code I'd be replacing is:
<table>
<tr>
<td>Name</td><td>Value</td>
</tr>
...
</table>
From what I've been reading I should have something like
<label class="name">Name</label><label class="value">Value</value><br />
...
Ideas and links to online samples greatly appreciated. I'm a developer way out of my design depth.
EDIT: My need is to be able to both to display the data to a user and edit the values in a separate (but near identical) form.
I think that definition lists are pretty close semantically to name/value pairs.
<dl>
<dt>Name</dt>
<dd>Value</dd>
</dl>
Definition lists - misused or misunderstood?
Horizontal definition lists work pretty well, i.e.
<dl class="dl-horizontal">
<dt>ID</dt>
<dd>25</dd>
<dt>Username</dt>
<dd>Bob</dd>
</dl>
The dl-horizontal class is provided by the Bootstrap CSS framework.
From Bootstrap4:
<dl class="row">
<dt class="col">ID</dt>
<dd class="col">25</dd>
</dl>
<dl class="row">
<dt class="col">Username</dt>
<dd class="col">Bob</dd>
</dl>
I think tables are best used for tabular data, which it seems you have there.
If you do not want to use tables, the best thing would be to use definition lists(<dl> and <dt>). Here is how to style them to look like your old <td> layout.
http://maxdesign.com.au/articles/definition/
It's perfectly reasonable to use tables for what seems to be tabular data.
If I'm writing a form I usually use this:
<form ... class="editing">
<div class="field">
<label>Label</label>
<span class="edit"><input type="text" value="Value" ... /></span>
<span class="view">Value</span>
</div>
...
</form>
Then in my css:
.editing .view, .viewing .edit { display: none }
.editing .edit, .editing .view { display: inline }
Then with a little JavaScript I can swap the class of the form from editing to viewing.
I mention this approach since you wanted to display and edit the data with nearly the same layout and this is a way of doing it.
Like macbirdie I'd be inclined to mark data like this up as a definition list unless the content of the existing table could be judged to actually be tabular content.
I'd avoid using the label tag in the way you propose. Take a look at explanation of the label tag # https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label - it's really intended to allow you to focus on its associated control. Also avoid using generic divs and spans as from a semantic point of view they're weak.
If you're display multiple name-value pairs on one screen, but editing only one on an edit screen, I'd use a table on the former screen, and a definition list on the latter.
use the float: property eg:
css:
.left {
float:left;
padding-right:20px
}
html:
<div class="left">
Name<br/>
AnotherName
</div>
<div>
Value<br />
AnotherValue
</div>