Definition Lists versus Tables

I remember a couple years ago speaking at An Event Apart and mentioning how I don't use the definition list. I may have said it a few times, to the annoyance of the audience. When pushed on why I don't use definition lists, I mentioned that screenreaders read out that a term is equal to a definition. Somebody tested and confirmed with me afterwards that his particular screenreader did in fact read it out in a way that would be awkward if people were to use them. (Alas, I can't remember exactly what it was that the screenreader actually announced.)

It's been a couple years since that fateful day and the situation came up at work. A co-worker was using a definition list and I mentioned the accessibility issue. A table was better. But was it? HTML5 indicates that definition lists are now data lists and can take any name/value content. Based on the spec, my co-worker was using the definition list correctly.

I decided to test which is better: a <dl> or <table>. In these tests, I'm using the only two screenreaders that I have available to me: VoiceOver (with Chrome 17 on Mac and Safari 5.1, both on Lion) and NVDA (Firefox 11 on Windows 7 via VMWare Fusion).

Game on!

The Design

The design is pretty typical: properties on the left, values on the right.

An Example Layout

The Definition List

I created a simple definition list.

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

NVDA'S behaviour here is interesting in that it just reads the items without announcing that it's a list or that the terms and definitions have any relation. The content is just read in a linear fashion.

VoiceOver is better in that it informs you that it's a list but it says it is a list with 4 items. That's not very helpful. It doesn't establish any connection between the terms and their definitions.

Based on this alone, I'd say that the DL isn't a great idea. So, what of the table?

The Table

I created a simple table with two rows and two columns.

<table>
<tbody>
     <tr>
         <td>Property</td>
         <td>Value</td>
     </tr>
     <tr>
         <td>Name</td>
         <td>Val</td>
     </tr>
</tbody>
</table>

NVDA nor VoiceOver provide any insight that this is a table. Once again, the content is simply linearized. This makes sense since tables are often used for layout instead of for semantics.

There are a few different approaches that can be used to inform the screenreader that it's a valid table and allow for a richer interaction experience.

Use header cells

Changing the keys to use a TH instead of a TD allowed the screenreaders to recognize that it was a table and navigate the table.

<table>
<tbody>
     <tr>
         <th>Property</th>
         <td>Value</td>
     </tr>
     <tr>
         <th>Name</th>
         <td>Val</td>
     </tr>
</tbody>
</table>

Interestingly, although the table could be navigated and you'd have a sense of rows and columns, neither NVDA nor VoiceOver in Chrome would announce that a particular cell was a header cell. VoiceOver in Safari 5.1, however, would announce the value of the header cell when switching rows. "row 1 of 2 property value" with a long enough pause between the words property and value so as to be able to tell that it's describing the heading for the cell.

For NVDA, adding a scope attribute to the header cell would allow the heading to be announced.

<table>
<tbody>
     <tr>
         <th scope="row">Property</th>
         <td>Value</td>
     </tr>
     <tr>
         <th scope="row">Name</th>
         <td>Val</td>
     </tr>
</tbody>
</table>

In this case, NVDA would say "property row 1 of 2 value".

ARIA Roles

The third approach I used was to specify the ARIA grid role to the table. This also required adding the row roles to each of the TRs.

<table role="grid">
<tbody>
     <tr role="row">
         <th>Property</th>
         <td>Value</td>
     </tr>
     <tr role="row">
         <th>Name</th>
         <td>Val</td>
     </tr>
</tbody>
</table>

Once again, NVDA and VoiceOver would read the cells but did not indicate any association between the header cell and the content cell. There are additional roles that can be applied on the cell—role="gridcell" and role="rowheader"—but neither provided any additional clarity to the screenreader.

Caption

The last technique to inform the screenreaders that the table was a table was to apply a caption to the table.

<table>
    <caption>Caption</caption>
<tbody>
     <tr>
         <td>Property</td>
         <td>Value</td>
     </tr>
     <tr>
         <td>Name</td>
         <td>Val</td>
     </tr>
</tbody>
</table>

What I noticed was that the caption could be hidden using display:none and the table would still be navigable in VoiceOver. Unfortunately, with NVDA, setting the caption to display:none (or even just position:absolute) seems to render the table like a layout table. That's not good.

Other Options

In testing other options, the only other alternative that I could find that seemed particular relevant was to identify the heading. This could be done in one of two ways: use a heading tag or use a heading aria role.

With the heading tag, the heading level is announced.

With the heading ARIA role, it'll announce "heading level 0" in VoiceOver but just "heading" in NVDA. The document outline should be smart enough to figure out that the ARIA heading. However, in neither Safari nor Chrome was it able to automatically figure it out. Specifying an aria-level attribute should help clarify things. Unfortunately, while Safari recognized this attribute, Chrome didn't. Finally, NVDA recognized and read out "heading level 2" correctly.

Recommendation

Of all the options, I'd use one of two approaches:

  1. Use a table with scope attributes on header cells; or
  2. Use an ordered or unordered list (but not a definition list) with headings (tags or ARIA)

I like the way that lists are announced and would therefore lean in that direction. Tables offer a lot of features but for a simple list of name/value pairs, a table feels like too much. Here is how I would code up the example:

<ul>
    <li><h3>Property</h3>
        <div>Value</div>
    </li>
    <li><h3>Name</h3>
        <div>Val</div>
    </li>
</ul>

Headings get floated to the left, divs get floated to the right, and list items clear floats. (Of course, use the proper heading level that is appropriate for your document.)

This was an interesting process to explore and I definitely have changed the way I would approach this in the future. Those with insights about other screenreaders are welcome to chime in.

Published March 25, 2012
Categorized as HTML and CSS
Short URL: https://snook.ca/s/1015

Conversation

38 Comments · RSS feed
Harri H said on March 25, 2012

Nice post, thanks for sharing. But uh-oh, I guess this is a good example how creating semantic and logical markup doesn't necessarily guarantee much what comes to accessibility and screen readers. Shame.

Damon Muma said on March 25, 2012

Fantastic! I would be so happy to see more of this sort of stuff studied. It's very easy to talk about semantics and best practice in a theoretical way without really field-testing anything.. especially since it's very difficult to field test screen readers (and also to know what the experience is like for non-sighted users!) Thanks for looking into this.

George Zamfir said on March 25, 2012

I think you've reached the right conclusion. I've been in your shoes fairly recently where I had to choose between tables and lists (ul or ol), I dismissed definition lists pretty early as well.

My dilemma was similar to yours in that the data (which fit in a 2-by-x table, with x < 10) being tabular I should've used a table but it was simple enough that it made more sense with (un)ordered lists. And the determining factor for me as well was that lists are correctly announced by screen readers (SR) across the board.

The <table> solution

However, those who have to use tables even for such simple content (because of framework limitations, etc.) should know that it's OK if the SR doesn't announce each cell header(s) as the user moves from one to another, it would be rather annoying especially for large tables to hear the headers for every cell. What SR users do is use their table-specific keystrokes to "read" the corresponding headers when they need to. Of course, in order for them to do that, they need the table to be marked-up with appropriate <th> and scope= attributes as you correctly identified.

On top of your table solution, one thing I would do differently, especially if you have multiple info areas (Support & Sales, Media, Shipping, etc.) which is usually the case, is to include the heading in the table. What this does is provide more context to each "Phone" / "Email" / "Website".


<table>
   <tr colspan="2">
      <th scope="col">Support & Sales</th>

Also, I'd be curious to know why you've tested with <caption> and not table <summary>.

I think that the great take-away is that one must use <th> and scope= where appropriate and not <td> everything, it makes more semantic sense and of course it's more accessible.

All in all a great post and the thought process is very insightful.

Jonathan Snook said on March 25, 2012

@George: Thank you for the in-depth response. As to the caption vs summary, I didn't think of it. Maybe I'll retest that when I get a chance. (And I assume you meant the summary attribute. I wasn't aware of a summary tag.)

Eric Eggert said on March 26, 2012

Hi Jonathan,

Thanks for the article, just a quick note: Chome isn't the best choice as the browser itself is largely inaccessible. The browser decides what he gives to the Accessibility API, and that's where chrome fails with th elements, it seems. Browsers have an algorithm that decides if a table is for layout or content purposes. A scope is a strong pointer that there isn't a layout table.

Most screen reader users I've talked to prefer linearisation on simple data tables, so I wouldn't mess with it. (And I'd use an ul li with spans for that example anyway ;-)

Anders said on March 26, 2012

So are you saying we shouldn't be using definition lists at all?

Tim Wright said on March 26, 2012

Excellent post. Just out of curiosity, is there any particular reason you went with a DIV in the last example over maybe a paragraph? (I realize the example value is a single word).

Thanks for the write-up, I'm always interested in reading accessibility studies as it's something we tend to take for granted.

Jonathan Snook said on March 26, 2012

@Anders: I'd say that the only time they should be used is for actual definitions but done in such a way that the term and definitions are obviously separated. I don't like the way screenreaders treat them, in any case.

@Tim Wright: I used a DIV because it's innocuous and with such a small phrase, a P seems heavy handed; I'd have to strip it of margin/padding anyways.

Holly Doggett said on March 26, 2012

I was surprised to see an H3 and a div inside of an LI. Does that validate?

Lars Gunther said on March 26, 2012

Hmmm....

First of all, if there is no scope="row" the th is not supposed to be a row header at all. So that was no surprise.

Second thought: How Firefox calculates if it's a layout table or data table.

Third thought: You're testing on a Mac? Accessibility in Firefox really shines on Windows and Linux. Thus we need lots of more tests before anything conclusive can be said.

Jonathan Snook said on March 26, 2012

@Lars Gunther: That Firefox link is fantastic. Thank you very much for that.

As to your thought regarding testing, I tested on a Mac and on Windows. Specifically, using NVDA with Firefox. More testing is welcome but this is the extent of which I can test. (I'd love to get my hands on JAWS but it's expensive.)

Thierry Koblentz said on March 26, 2012

Hi Jonathan,

For what it worth I don't agree with this approach.
I believe if the support for DL is that bad, it is because (screen-reader) vendors didn't see the need to support this element since it is not much used in the wild.

Choosing to ignore this semantically rich element for a11y reasons should do nothing more than reducing the chances to see SR vendors take this issue into consideration.

Of course, the other problem is that many authors have a hard time styling Definition Lists - which does not help.

So I'll finish with a shameless plug Definition Lists, Glossary and Table format

Maxim said on March 26, 2012

Great post. However, I can not agree more with Thierry Koblentz.

Andy Hawkes said on March 27, 2012

The one thing I have always hated about the definition / description list is the lack of an enclosing <li> element around individual term / data groups - you can have multiple data items per term but there are limited means of semantically grouping/separating them in a way that would also work visually when you have a theoretically many-to-many relationship between <dt> and <dd> elements.

For me it's one of those rare elements that has a theoretical semantic meaning and could be used appropriately but is generally more hassle than it's worth in the real world.

Lee Kowalkowski said on March 29, 2012

I agree with Thierry too. You said: "Based on this alone, I'd say that the DL isn't a great idea.", that struck me as odd, because my conclusion was that it was the screen readers that did a shamefully poor job, all the required semantics are there.

It also appears TABLE and UL didn't work well in the screen reader before applying additional effort, yet there's no mention of any such effort being spent to help DL work better, e.g. using ARIA. If DL is semantically appropriate, then use it. Assistive technology will catch up eventually.

There's nothing wrong with a two-column table if you have a 1 to 1 relationship, the decision between DL or TABLE is truly optional in that instance. But DL also supports 1 to many, many to 1 and many to many, trying to achieve that with a TABLE is not as clean/terse.

I found the UL LI Hn structure awkward too, and not a good substitute for when it's not a simple 1 to 1 relationship. I'm not sure screen reader users would be comfortable hearing a list of something and having headings announced within it, sounds kinda noisy.

Ideally, there should never be the advice "do not [properly] use a construct because its support in a particular technology is poor", that should be a reason for not choosing the technology, think IE6. Although NVDA is actively developed, so it just needs raising with them (if your findings are still true when using the latest version).

http://webaim.org/discussion/mail_thread?thread=3463#post12 Says JAWS announces and supports user-navigation through a definition list, so does Windows Eyes. (2008)

http://www.nomensa.com/blog/2011/using-html-lists/ describes the behaviour of definition lists in screen readers.

Jonathan Snook said on March 30, 2012

@Lee Kowalkowski: Of note, I did look at what ARIA roles could be applied to the definition list that would allow the screenreader to better understand the list.

The problem with "assistive technology will catch up" is that for people who need screenreaders, there isn't a lot of options. And it's not that I'm recommending no semantics or a lesser experience. I'm recommending descriptive and semantic HTML elements that also allow screenreaders to navigate the content in a way that, I think, makes sense and do so rather consistently across screenreaders.

For example, I don't use HTML5 elements on which I have to rely on styling unless i can guarantee JavaScript support. Yes, user agents can and are catching up but I want to be as inclusive as possible whenever possible. Why should I destroy the experience for a subset of users just for code purism? And why does code purism only stand at the HTML? Why not the CSS or the JavaScript? /this last paragraph was also in response to Thierry.

Lee Kowalkowski said on March 31, 2012

Thanks Jonathan, but I'm not sure your perception of screen reader support is up to date enough to justify not using definition list.

Looking at Surveys of screen reader users, most users are using JAWS and WindowsEyes, and definition list work fine in them (and NVDA in Internet Explorer).

The respondents over time have growing faith in free/default screen readers, but most are still using the commercial heavyweights.

An NVDA ticket reports this issue as fixed and specific to how Firefox exposes the elements (Firefox bug).

For new technologies (HTML5/CSS3) I also prefer to hang fire and wait for the native support before using them on the internet for crucial applications, just to be inclusive.

If it's between being purist of code and purist of what devices I support, then yes I suppose I'm choosing to be a purist of something over which I have control. Besides, there are some really awful devices out there.

The exclusion of specific devices is not deliberate, I have no control what device is used. It's the device that is excluding the user, not me, so we should not be making scapegoats out of other things.

Definition list is not new, and screen readers really ought to support them properly (and apparently, most of them do nowadays, some results even say VoiceOver does).

If you're still really concerned about the unsupported devices, you can always create a runtime shim (I dunno, stick a <dfn> element inside your <dd> or something). That seems to be the approach of choice for unsupported HTML5/CSS3 just lately.

I didn't really follow the "why not also CSS or JavaScript?" part. Did somebody say they shouldn't be included? Don't we like everything to be as pure as possible? We like to be inclusive in what we like to be pure, I'd like to think. I'd like the screen readers to be pure also. If you make your HTML impure in response to an impure screen reader, that's pollution, and I'm starting to write really weird things now so...

In a nutshell, I think support is adequate to go ahead and use the definition list without criticism. The inadequate screen readers must catch up if they really still haven't.

Reinier Kaper said on April 03, 2012

Honestly I don't think semantics should be adapted to the capacity of screen readers, but the other way around.

If you have data that "should" go into a table (tabular data) or in a list (typically a (linear) list of items), then I think it's a good idea to keep it that way.

You should not try to compensate for the (in)ability of screen-readers to making a (logical) connection between elements, it's what got us in this "mess" in the first place.

Also, it might be worth testing with Jaws as it's a highly popular screen-reader (but as far as I know it doesn't work in virtual environments).

Just my 2 cents of course ;-)

Reinier Kaper said on April 03, 2012

I forgot to add that it's an interesting read of course and it displays the gap there still is between structured data and the way it's presented (in a medium independent way).

Matthew James Taylor said on April 07, 2012

I think its a shame to use a table when a definition list is clearly more semantically correct. Screen readers need to follow standards just like browsers otherwise we're all wasting our time. We should be coding to standards, not to the quirks of particular browser's (or screen readers).

Frederico Cerdeira said on April 07, 2012

Hi. Im agree with with Matthew. DL represents more semantic content than tables. SR should follow closely the web standards. The standards should be the only design way.

Vlad said on April 07, 2012

Disagree with previous reviewers. The job of the designer is not to design "to spec". his job is to think of the user and do what works. If screen readers are at fault, they need to be encouraged to do better. In the mean time, if the "correct" approach does not give the user what they need, then it's not the right approach.

alexmarkup said on April 09, 2012

Ok, but what about Jaws screenreader, the most used by the organisations that install that kind of soft ?

alexmarkup said on April 09, 2012

Ok Sorry, id just read above.... DL works fine in JAWS. I think that all accessibility testing should be done with Jaws software

Look at this doc. Its in french but a wcag 2.0 very well explained.

alexmarkup said on April 09, 2012

http://certif.accessibiliteweb.com/accueil/base-de-connaissances/

Jonathan Snook said on April 10, 2012

JAWS is hard to test for on a Mac but it does, indeed seem to have the best support for navigating definition lists. However, JAWS—based on the survey linked earlier—only has a 60% share and I suspect that number is in decline with free alternatives (like NVDA and VoiceOver) appearing on the market. "Most notable is a significant decline in primary usage of JAWS" and this was back in 2010.

Is there a reason why you'd knowingly make the experience worse for potentially 40%+ of your audience? And for what? A generic list or a table is still completely relevant in describing the content. I'm not describing a bastardization of semantics... just alternatives. In fact, the definition list seems the least relevant as we're not defining terms. An address doesn't define "email", it's a value of. (But yes, HTML5 does change this to make it more generic and relevant.)

Now if you'll excuse me, I'm going back to designing IE-only sites.

Reinier Kaper said on April 10, 2012

The black/white view would be between 100% semantics (if there's such a thing) and 100% user experience (if there's such a thing).

I tend to lean more toward semantics, because I honestly believe if most people follow standards and best practices, browsers HAVE to keep up. The days of IE only are over and it has become clear that people want browsers that actually behave predictably.

Text-readers are always the odd one out because most people don't care about them and/or don't test them (or don't have the means to). Mainly because this group is relatively small as well.

I'm of the opinion that if a text reader can't sufficiently "connect the semantic dots", then that's something they should change, not me. Should I go the extra mile to try and make their experience best as I can? Possibly, but I won't give in to bad practice for that.

I guess it simply boils down to what you think is more important in this case ;-)

fjpoblam said on May 08, 2012

I can *somewhat* see your reasoning, in a generic way, as applied to a non-descript reading of the words "property value". However, if the selfcheck machine at my grocery store reads to me, "phone, 800-555-1212, email, myname@mydomain.com" I have no problem understanding the associations. It may well be that these were formatted as a dl, and it may well be that they were formatted as a table. But I had no problem understanding them.

Niels Matthijs said on May 08, 2012

An nice way of looking at it. I would use a simple list or even div structure myself. It's not really a table (one could try to argue that it's a one-col table but since multiple columns wouldn't make sense in this situation a table just doesn't feel right). Definition lists are cool, especially if you take the html5 definition, but the fact that they miss a list item wrapper just plain sucks.

Oh, and one thing ... screenreaders should get their act together. We got browsers to shift gears, screenreaders should definitely follow.

Niels Matthijs said on May 08, 2012

Oh, and one more thing: why use a float:left/float:right construction when float:left/margin-left is way more stable?

Christian Mueller said on May 09, 2012

Did you try any aria roles on a DL and see how that performs?

Jonathan Snook said on May 10, 2012

@Niels: the float:left/right with a clear float seems like the most appropriate approach. I'm not sure in what way it would be considered unstable.

@Christian: I looked at ARIA roles and didn't see any that would be appropriate for this situation.

Reinier Kaper said on May 15, 2012

Recently I have found a way that seems to perform nicely (albeit not thoroughly tested for screen readers), with the help of a slightly "unsemantic" helper-class in HTML% boilerplate.

I would style this element as an unordered list (after all, it's a lit of information), where I would use the following structure:

<ul>
 <li>Phone: 613-000-1111</li>
 <li>E-mail: me@somewhere.com</li>
 <li>Website: www.mysite.com</li>
</ul>

Now the nice part comes in at the colons, which I wrap in a span with the 'visuallyhidden' class. What this does it hides it from visual browsers, but it will still be present for screen readers and it makes a lot of sense.

I also use this for headings that have sub-headings, which semantically are part of the actual heading (example "Annual report: 2012 a year in review", where I put the colon in a span and hide it from view and wrap the sub-heading in a span or div (depending on block/inline)).

What do you think about something like that?

Jonathan Snook said on May 16, 2012

@Reinier: I think that it's a potentially valid option. As long as it is descriptive and makes sense when read aloud, go for it.

Alex O'Neal said on May 25, 2012

You know, I was in the anti-definition list camp myself for years, but never took the time to methodically test things out like this. Excellent and insightful - thanks for sharing :-)

Darrel Austin said on November 05, 2012

First, a complete aside, but it's nice to see blog discussions like this still take place. Twitter and Facebook have distracted us from meaty (albeit niche) discussions like this. :)

I stumbled upon this conversation googling this very question myself. I have a small-ish table of less than 10 rows of simple label/value pairs. A table was the go-to choice but the markup seemed excessive for such a small table.

So DL made the next-best sense. Glad to hear JAWS supports it, though I too disagree that a) we should pander to JAWS or b) pander to screen readers in general that don't support proper markup to begin with.

One thought I had was to stick with DL, but add a dividing character of some sort, such as a colon.

Visually I can justify it, but can't say if the colon offers any benefit to screen readers (or worse, if it hampers comprehension).

Since I'm working on an iOS app at the moment, I though I'd run some options through iOS's VoiceOver.

I made two sets of DLs (one with a colon separator, and one without) and two tables (one with THs and one without):

http://jsbin.com/operid/2/edit

The verdict? At least with VoiceOver, those are all read exactly the same. VoiceOver ignores the colon (which probably makes sense) and also does nothing special for the TH.

And, in the end, I think that's probably OK. Again, these are simple lists of label/value pairs and having them read linearly perhaps isn't so bad.

Wayne Fuller said on March 08, 2013

Jonathan;
Nice article, well written.

Just one thing: Am currently taking an HTML course at a local CC. The instructor has indicated (and this is not the first time I have heard this) that TABLES is one of the many tags that will be going away.

Wayne

Jonathan Snook said on March 08, 2013

Wayne, tables will not ever go away. Using them for layout only already mostly has (gone away).

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.