FE / HTML / a11y

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 and
  • dl 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 &amp; 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&nbsp;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&nbsp;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.

Comments