ARIA Lists
ARIA’s list
and listitem
roles allow for developers to change the semantics of other HTML tags to announce themselves as lists, and items within a list, respectively.
More often than not, using native ul
, or ol
, elements is the ideal method to markup each type of list (I didn’t forget about dl
s. I’m going to talk about those another day). But there may be times when native elements can’t be used, or you’re stuck working with a sea of legacy or 3rd party div
s, and you’ll need to lean on ARIA to modify a document’s markup to be more semantic and accessible.
Ordered, unordered, it’s all the same to ARIA
Since ARIA role="list"
is based on the native HTML ol
and ul
elements, one might wonder how it could announce itself as one or the other? Well, it can’t. But that’s OK, because if you navigate to native ol
and ul
elements with screen readers, you’ll notice each list type doesn’t immediately announce themselves as either an ordered or unordered list. The type of list becomes clear once you start interacting with the different list items within. By default, these native list items will have a number announced for ordered lists, and a “bullet” for unordered lists.
Providing the context to the type of list an ARIA list
is meant to represent can be done with CSS.
CSS for “unordered” listitem
s
As ARIA only affects the semantics of a HTML tag, and not its native functionality or appearance, there are no bullets for screen readers to pick up on to announce.
For unordered listitem
s, this may not be an issue for simple lists, as each listitem
can still be navigable by screen reader quick keys (more on that later).
But if dealing with nested unordered lists, it’d be optimal to provide an audible cue that would allow users to easily identify the nested list they are in.
To add “bullets” or other list styles to a listitem
, the following CSS would be needed:
[role="listitem"] {
display: list-item;
}
.pretend-ul [role="listitem"] {
list-style: disc; /* default bullet */
}
/* a nested list should have a different glyph */
.pretend-ul [role="listitem"] [role="listitem"] {
list-style: circle;
}
/* and etc. */
.pretend-ul [role="listitem"] [role="listitem"] [role="listitem"] {
list-style: square;
}
CSS for “ordered” listitem
s
Where it’s fairly straight forward to add non-incremental glyphs to unordered listitem
s (straight forward being a relative term in regards to how many nested lists you have to support), if you try to add list-style: decimal;
to mimic an ordered list, you’ll notice it doesn’t work out so well.
To get around listitem
s not auto-incrementing like native list items do, CSS counters can be used instead.
The following example demonstrates an ARIA list with CSS counters used to add in the increments.
ARIA "ordered list" example
(This example and more can be viewed here: Ordered ARIA lists using CSS counters CodePen.)
As with many other things not supported by Internet Explorer, screen readers paired with IE won’t announce the CSS counters. But testing with NVDA & JAWS in Chrome, and Firefox, as well as VoiceOver & Safari (desktop and mobile), will announce the counters largely as if they were native list items of an ol
element.
Grouping list items
Where a native ol
or ul
element can only have li
elements as direct children, an ARIA list
has a looser expectation for child elements since the native semantics and markup expectations for the native lists won’t apply.
As an example, the following markup pattern is valid for an ARIA list
:
<div role="list">
<div role="presentation">
<div role="listitem">...</div>
<div role="listitem">...</div>
</div>
<div role="presentation">
<div role="listitem">...</div>
<div role="listitem">...</div>
</div>
</div>
The role="presentation"
is necessary to appropriately convey the number of listitem
s to NVDA + Firefox. Without the role="presentation"
, NVDA would only announce the “list” as having “two” items within it, though each of the listitem
s would still be navigable by quick keys.
Speaking of Announcements
If you want to test how different screen readers interpret ARIA lists, you can check out the following CodePens:
Unordered ARIA lists announcements
If you don’t have access to a bunch of devices and screen readers, here is a summary per how screen readers interact with list
and listitem
s per the “Unordered ARIA lists” CodePen.
Native ul
and ol
announcements
Safari + VoiceOver (desktop High Sierra)
Focusing on the native list wrapper, VoiceOver will announce "list # items"
For ul
list items, VoiceOver will announce "bullet, accessible name, x of y"
For `ol` list items, VoiceOver will announce "#, accessible name, # of y"
VoiceOver will announce when a user has reached the end of a list.
Safari + VoiceOver (iOS 11.3.1)
Navigating by lists with VoiceOver rotor, the first bullet or # will be focused when swiping up or down. Having VoiceOver announce "bullet, list start" or "#, list start".
For ul
list items, VoiceOver will announce "bullet" and then require a second swipe to read the content of the list item.
For ol
list items, VoiceOver will announce "#" and then require a second swipe to read the content of the list item.
When navigating to the last list item in a list, VoiceOver will announce "list end" after the content of the last list item is announced.
JAWS 2018 + Edge
Focusing on the native list wrapper, JAWS will announce "list of # items" and then immediately announce the first list item.
For ul
list items, JAWS will announce "bullet, accessible name".
For ol
list items, JAWS will announce "#, accessible name".
JAWS 2018 + IE11 / Firefox ESR / Firefox Nightly 62 / Latest Chrome
Focusing on the native list wrapper, JAWS will announce "list of # items".
For ul
list items, JAWS will announce "bullet, accessible name".
For ol
list items, JAWS will announce "#, accessible name".
NVDA 2018.1 + Firefox ESR / Firefox Nightly 62 / Latest Chrome
Focusing on the native list wrapper, NVDA will announce "list of # items" and then announce the first list item of the list, in the format of how NVDA announces individual list items.
For ul
list items, NVDA will announce "bullet, accessible name".
For ol
list items, NVDA will announce "#, accessible name".
ARIA list
and listitem
announcements
Safari + VoiceOver (desktop High Sierra)
For role=list
with listitem
elements without display: list-item
VoiceOver will announce the accessible name, and the x of y for each list item.
If the listitem
elements have display: list-item
and a list-style: disc
, VoiceOver will announce "bullet, accessible name, x of y" for each list item.
VoiceOver has no issues announcing or navigating "grouped" lists regardless of role="presentation"
being used or not.
Safari + VoiceOver (iOS 11.3.1)
When navigating by lists with VoiceOver rotor:
For role="list"
with listitem
elements not set to display: list-item
VoiceOver will announce the accessible name of the first list item, and then announce "list start".
If the listitem
elements have display: list-item
and a list-style: disc
, VoiceOver will announce "bullet" and then "list start".
When navigating to the last list item in a list, VoiceOver will announce "list end" after the content of the last list item is announced.
VoiceOver has no issues announcing the number of items in a list, or navigating "grouped" lists regardless of role="presentation"
being used or not.
JAWS 2018 + Edge
JAWS + Edge will navigate to an ARIA list by use of the l key. It will not announce the number of items within the list though...
And using i quick keys, JAWS + Edge do not recognize ARIA listitems
.
When navigating by the virtual cursor, JAWS + Edge will announce a bullet if provided by CSS, so this is the only way to effectively convey a listitem
to Edge users.
JAWS 2018 + IE11
Unlike Edge, IE11 does recognize both role=list
and role=listitem
s.
Quick keys work to navigate by list or list item. When first navigating to a list, JAWS will announce how many items are within the list, but will not announce the current list item #, nor will it announce the bullets provided by display: list-item
and a list-style: disc
.
IE11 + JAWS have no issues announcing the number of items in a list, or navigating "grouped" lists regardless of role="presentation"
being used or not.
JAWS 2018 + Firefox ESR & Firefox Nightly 62
Navigating to a list
JAWS will announce "list of # items".
For role=list
with listitem
elements not set to display: list-item
JAWS will announce the accessible name of each listitem
.
If the listitem
elements have display: list-item
and a list-style: disc
, JAWS will announce "bullet, accessible name" for each list item.
Firefox + JAWS have no issues announcing the number of items in a list, or navigating "grouped" lists regardless of role="presentation"
being used or not. However, the CSS bullets are not announced.
JAWS 2018 + Chrome latest
Navigating to a list
JAWS will announce "list of # items".
For role=list
with listitem
elements not set to display: list-item
JAWS will announce the accessible name of each listitem
. The virtual cursor will *not* visually highlight these list items, though no other issues with navigation seem to exist.
If the listitem
elements have display: list-item
and a list-style: disc
, JAWS will announce "bullet, accessible name" for each list item.
Chrome + JAWS have no issues announcing the number of items in a list, or navigating "grouped" lists regardless of role="presentation"
being used or not.
NVDA 2018.1 + Firefox ESR & Firefox Nightly 62
Navigating to a list
NVDA will announce "list of # items" and then announce the first list item of the list, in the format of how NVDA announces individual listitem
.
For role=list
with listitem
elements not set to display: list-item
NVDA will announce the accessible name of each listitem
.
If the listitem
elements have display: list-item
and a list-style: disc
, NVDA will announce "bullet, accessible name" for each list item.
Firefox + NVDA will incorrectly announce the number of listitem
s in a list, if listitem
wrappers do not have a role="presentation"
set.
NVDA 2018.1 + Chrome latest
Navigating to a list
NVDA will announce "list of # items" and then announce the first list item of the list, in the format of how NVDA announces individual listitem
.
For role=list
with listitem
elements not set to display: list-item
NVDA will announce the accessible name of each listitem
.
If the listitem
elements have display: list-item
and a list-style: disc
, NVDA will announce "bullet, accessible name" for each list item.
Chrome + NVDA have no issues announcing the number of items in a list, or navigating "grouped" lists regardless of role="presentation"
being used or not.