Consideration on lists and accessibility: ul vs ol vs dl
Lists are great for accessibility but sometimes it can be tough to pick up the right one.
The official docs are far from perfect as well. Way too much into definitions and way too short on examples. And so, questions like “is this a good case for a list?”, “which one should I use?” or “is it ok to use an ol instead of a ul?” may definitely pop in your mind.
Why would you need a list anyway?
Supposedly, lists help with accessibility. They provide context to the reader, visually and semantically.
In particular, they warn about group of things in the page, the number of items in it and the order.
So, this is why. They are a good practice for accessibility.
Should I always use a list?
Not always, actually.
Although the use of this markup can make lists more readable, not all lists need markup. For instance, sentences that contain comma-separated lists may not need list markup.
— w3.org
As w3.org says, if you have a list of things in a sentence and it reads better as a sentence then keep it as a sentence.
It’s when you start using *
or -
to visually simulate a list that you should start using the html list tags.
Which types of lists are available and which one should I use?
There are 3 types of lists:
ul
unordered list,ol
ordered list anddl
definition list.
ul: unordered list
ul
defines plain list. The only relationship that express is that the items are grouped together.
Some interesting use cases are link lists, menu link lists and breadcrumbs.
Despite using nav
with ul
for link lists being considered a best practice, there is some talking about using div
and span
instaed.
<!-- Case: generic link list -->
<nav aria-labelledby="title">
<h3 id="title">ABOUT US</h3>
<ul>
<li><a href="…">About ....</a></li>
<li><a href="…">Careers at ...</a></li>
<li><a href="…">Sustainability</a></li>
<li><a href="…">Newsroom</a></li>
<li><a href="…">Investor centre</a></li>
</ul>
</nav>
<!-- Case: menu link list -->
<nav aria-label="Main Menu">
<ul>
<li><a href="…" aria-current="page">Home</a></li>
<li><a href="…">About</a></li>
<li><a href="…">Blog</a></li>
<li><a href="…">Contact Us</a></li>
</ul>
</nav>
<!-- Case: breadcrumbs -->
<nav aria-label="Breadcrumb" lang="en">
<ul>
<li>
<a href="/WAI/" lang="en">Home</a>
</li>
<li>
<a lang="en" href="/WAI/design-develop/"><span>Design & Develop</span></a>
</li>
<li>
<a lang="en" href="/WAI/tutorials/"><span>Tutorials</span></a>
</li>
<li>
<a lang="en" href="/WAI/tutorials/page-structure/"><span>Page Structure</span></a>
</li>
<li>
<a lang="en" href="/WAI/tutorials/page-structure/regions/" aria-current="page"><span>Page Regions</span></a>
</li>
</ul>
</nav>
Note: that for all the cases we used nav
as page region as we grouped links.
Also, see the use of aria-labelledby
, aria-label
to title the page region and the use of aria-current
to state the current active page.
ol: ordered list
ol
— as the name suggests — is used to state lists… with an order.
If you find yourself thinking “first…, second…” or “do this and then that” about a list, then it’s an ordered list you want to use.
And so, procedures, time sequences, text to be referenced are all good cases for ol
.
Some interesting use cases are action lists and laws (e.g. in footnotes).
<!-- Case: action list -->
<section aria-labelledby="title">
<h3 id="title">Bread Recipie</h3>
Some text here
.
.
.
<ol>
<li>Weight all the ingredient</li>
<li>Put water in a bowl</li>
<li>Add yeast</li>
<li>Add flour</li>
<li>Mix</li>
.
.
.
</ol>
</section>
<!-- Case: laws list -->
<section aria-label="Footnote">
Some text here
.
.
.
<ol>
<li id="footnote-3">Requires an ... account and compatible ... device with the latest operating system software.</li>
<li id="footnote-4">Compatible hardware and software required. Works with compatible content in supported apps. Not all content available in ....</li>
.
.
.
<li id="footnote-8">Battery life depends on device settings, environment, usage and many other factors.</li>
</ol>
</section>
In these cases, we used a section
but it could have been a div
.
For the footnotes, it’s interesting the use of id
in the li
tag as it provides quick access to each point.
dl: definition list
dl
can be used for any key
, value
type of list, where the value
tells you something about the key
.
Despite being less popular than ul
and ol
, dl
can cover cases like product details, value reports and similar.
When I started exploring this tag I was quite confused by the definition
part of the name. I thought it had to be a dictionary type of definition. But that was a mistake.
It’s all about the key
, value
relationship.
<!-- Case: nutritional fact -->
<div>
<h3>Nutritional Facts</h3>
<dl>
<dt>Proteins</dt>
<dd>10%</dd>
<dt>Carbs</dt>
<dd>1%</dd>
<dt>Fiber</dt>
<dd>1%</dd>
</dl>
</div>
<!-- Case: production report -->
<div>
<h3>Month of April</h3>
<dl>
<div role="none">
<dt>Fixed costs</dt>
<dd>Stable</dd>
</div>
<div role="none">
<dt>Variable costs</dt>
<dd>-10%</dd>
</div>
<div role="none">
<dt>Revenue</dt>
<dd>+1%</dd>
</div>
<div role="none">
<dt>Profit</dt>
<dd>+1%</dd>
</div>
</dl>
</div>
If you need extra support to create a row in your UI you may use role="presentation"
or role="none"
.
In this way, the extra div
is there visually but removed from the accessibility tree.
Legacy code
What if you need to improve the accessibility of an old codebase? Maybe the type of codebase where everything is a div
and even the smallest change is pure pain.
Then you can use the role
attribute.
In particular, you can use role="list"
to simulate an ul
and role="listitem"
for a li
.
While not recommended as the primary way to mean a list, the use of role
can be an effective way to lift up some of your page semantics.
The only drawback is that in this way you can’t express ol
, it will always be treated as ul
list.
<!-- Case: div ul list -->
<div role="list">
<div role="listitem">
Article card
<a href="">Go to article</a>
</div>
<div role="listitem">
Article card
<a href="">Go to article</a>
</div>
</div>
While for definition lists, use role="listitem"
to simulate the dl
, role="item"
for dt
and role="term"
for dd
.
With this approach, we do lose a lot of semantics as it turns the list to a ul
with a term in it. But again, it’s an extreme compromise for an extreme case.
<!-- Case: div ul list -->
<div role="list">
<div role="listitem">
Implementation report:
<div role="term">link to report</div>
</div>
<div role="listitem">
This version:
<div role="term">link to version</div>
</div>
</div>
Summary
We saw the html tag list which are ul
, ol
and dl
. For each list type, we looked at some cases with examples.
Then we saw how to rescue legacy html using the role
attribute; in particular, role="list"
and role="listitem"
.
With this in mind, you should be able to use the appropriate list tag or role and have a sense of the trade-off in the accessibility context.
If you want to dig further, I would suggest reading Scott O’Hara’s Aria Lists, Navigation in Lists: To Be or Not To Be and Using ol, ul and dl for lists or groups of links.
Links
- H48: Using ol, ul and dl for lists or groups of links
- W3C Superseded Recommendations: List
- Page Regions
- "Fixing" Lists
- Navigation in Lists: To Be or Not To Be
- Aria Lists
- ARIA: term role
- ARIA in HTML
- Chrome: Screen Reader