Implicit ARIA landmark roles
First posted 14th June 2019 in Accessibility and Development; updated 24th August 2020
ARIA roles are a way to define various landmarks on a webpage; things like:
- The header
- The main navigation
- The search box
- Complementary content
- The main content area
- The footer
They give a screen reader user an easy way to orient themselves on a web page by naming the main areas on the page; exactly as a sighted user would identify the same areas at a glance.
Some of these landmarks can be used a few times, for example, there may be primary and secondary navigation menus, but other landmarks only make sense when they’re unique:
- You should only have one header on a page
- There can only be one main content area
- One page footer is all you need
So far so good. But what about implicit mappings? This means that a <header>
should automatically be interpreted as having a role="banner"
and a <footer>
should get a role="contentinfo"
, but that can’t be right if we’re allowed to use multiple <header>
s and <footer>
s…
The theory
The answer lies in sectioning elements. The W3C specification says a role of banner
will be automatically assigned to a <header>
element unless it’s
a descendant of an article, aside, main, nav or section element
So only the first header
element in this next example will get an implicit ARIA landmark role:
<body>
<header>
<h1>This is a great heading</h1>
</header>
<p>Isn't this great content?</p>
<section>
<header>
<h2>This is a nested section</h2>
</header>
<p>Here are some details about the nested section.</p>
</section>
</body>
The browser knows the main page header is the first <header>
and not the second one because:
- the first is a child
<header>
of the<body>
element - the second one is separated from the
<body>
element by being wrapped in<section>
tags
In practice
In my testing (on VoiceOver on macOS 10.14.5), this only seems to work with <article>
and <section>
elements. <main>
, <nav>
and <aside>
don’t scope their nested <header>
as the specs suggest they should, so the document gets two implicit role="banner"
elements. This is bad.
Also, the same principle is supposed to be true for the <footer>
element, but it doesn’t add role="contentinfo"
implicitly.
Update: Turns out this was a bug with VoiceOver/Safari and has since been fixed!
The annoying thing
Browser support is a thing in frontend development, and unfortunately/predictably if you want to support Internet Explorer (and I’m not talking about IE8; I mean any version, including the most recent, IE11) you have to be explicit with your roles.
But the thing that bugs me about all of this is that the WC3 page on ARIA in HTML tells us
Setting an ARIA
role
and/oraria-*
attribute that matches the implicit ARIA semantics is unnecessary and is NOT RECOMMENDED as these properties are already set by the browser
Now, where I’m from, all-caps aren’t use lightly. In fact, I’m pretty sure it’s not recommended to use all-caps to emphasise text in HTML… (Granted they’re using <em>
tags, but isn’t <strong>
the proper way to ramp up the emphasis? Naughty.)
I get that adding role="heading"
to a heading is unnecessary, but if the implicit ARIA roles aren’t working, I’m still going to have to do something manually.
What to do
So the principle is sound:
- Don’t worry about ARIA landmark roles as the browser is smart enough to add them for you
- Use as many headers and footers as you like, but make sure they’re scoped inside a sectioning element
But as you can see, this isn’t the case.
I’ll be continuing to add role=""
attributes to elements that I want to be landmarks. Assuming the browser will add them for me means some could be missed.
I’ll also feel more comfortable using more than one <header>
on a page, but it’ll only be doing it inside either an <article>
or <section>
– I don’t want any rogue landmarks being created!
If only frontend development were easy!