Know your ARIA: 'Hidden' vs 'None'
ARIA provides two different methods for suppressing accessibility information of a page’s markup.
role=none | presentation. What they do can sometimes be confused by developers. Are they the same? Are they different, and if so, how?
Let’s break down each.
aria-hidden attribute indicates whether an element is exposed to a user agent’s (e.g., a browser’s) accessibility API, or accessibility tree.
If an element has been marked as
aria-hidden=true, the element and any of its descendants are to be hidden from assistive technologies (such as screen readers), regardless of whether the element is visually rendered or not.
Conversely, If the element has
aria-hidden=false it is meant to be exposed to assistive technologies as if the attribute were not set at all. Be warned, as noted in the ARIA specification, there may be issues with using
aria-hidden=false. If you are not intending to hide the content, it’s probably best to just remove the attribute rather than use it with the
aria-hidden without a value will default to the current state of the element. Essentially, this would mean
aria-hidden is ignored and the element would be exposed, or not, depending on other properties of the element.
<p aria-hidden hidden>...</p> would be hidden because the
hidden attribute, and its default user agent styling of
display: none, have already stopped the element from being exposed to the browser’s accessibility tree.
<p aria-hidden style="opacity: 0">...</p> would not be hidden because a zero opacity element is only visually hidden. It and any of its contents is still exposed to assistive technologies.
A general rule to follow is that if content is being hidden from some users, that content probably needs to be hidden from all users. That means that often
aria-hidden=true may not be what you really need.
For instance, to fully hide content from everyone, use CSS
display: none or
visibility: hidden. Both of which are far more robust methods of hiding content to everyone.
Alternatively, the HTML
hidden attribute could be used, which will keep content hidden even in instances where author CSS may become unavailable (for example, a browser’s reader mode). But because of this, you want to be very careful in its use.
aria-hidden=true by itself is not enough to completely hide an element from all users, if that is the end goal.
In the following markup example, the paragraph is hidden to assistive technologies, but it otherwise remains visible.
<p aria-hidden=true> This content is not announced to screen readers. </p>
ARIA attributes only impact the way content is exposed to the accessibility tree, and do not alter the functionality or styling of elements without further customization by web developers.
aria-hidden=true in this way could pose an issue for sighted or partially sighted users who may also be using assistive technologies. There’s clearly content there… why can’t it be reached?
The following examples are completely hidden to all users:
<p hidden>...</p> <p style="display: none;">...</p> <p style="visibility: hidden;">...</p>
If content needs to be hidden from all users, but other styling mechanisms are used to do so, then
aria-hidden=true can be used to achieve this goal.
<p aria-hidden=true style="opacity: 0"> ... </p>
In the previous markup example, if there were a hyperlink (
<a href=...>) or
<button> element within that otherwise hidden paragraph, the Tab key would still be able to reach the visually hidden focusable element.
aria-hidden=true does not stop a focusable element from being focusable.
An example of where
aria-hidden=true can be useful for hiding visual content from assistive technologies is when an element represents content that could be considered decorative, or duplicative, to equally accessible content that is rendered on the page.
For instance, a hyperlink containing an icon that accompanies sibling text. An icon’s alternative text would often be redundant in such a case, so it would be better if hidden to assistive technologies.
<a href="/"> <span class=home-font-icon aria-hidden=true></span> Home </a>
aria-hidden=true can be used to hide an element and its descendant content from assistive technologies, the
presentation roles are to be used to only suppress the implicit ARIA semantics of an element. These roles do not hide the element’s content from assistive technologies. Furthermore, setting an element’s
role to one of these values does not change the semantics of any element that is a descendant of the now “presentational” element, with one exception (outlined in the next section).
noneare synonyms of each other.
In ARIA 1.1, the working group introduced
noneas a synonym to the
presentationrole, due to author confusion surrounding the intended meaning of the word "presentation" or "presentational." Many individuals erroneously consider
role=presentationto be synonymous with
aria-hidden=true, and we believe
role=noneconveys the actual meaning more unambiguously.
Ideally, you would not use these roles too often. Being that their purpose is to negate the implicit ARIA semantics of the elements they are used on, their use may indicate that a more generic element (a
<div> for instance) should have been used instead.
<!-- avoid --> <article role=none> <p>I'm still exposed as a paragraph!</p> <button>I'm still exposed as a button!</button> </article> <!-- instead --> <div> <p>...</p> <button>...</button> </div>
That said, there are times when these roles are beneficial. They can be used for correcting legacy markup misuse, as well as specific instances for modern day web development.
The most common example of needing to correct HTML mistakes of the past is with the
<table> element. Tables were widely abused for layout purposes before more sophisticated CSS layout techniques were created. Fortunately, invalid use of tables have largely stopped, but there are many legacy websites where these tables might still be found – and truly there are even some more modern day websites where developers have repeated past mistakes as a quick way to layout content.
To remove unwanted table semantics from these “layout tables”, a
role=none can be specified on the
<table> element. When a
<table> element has its implicit ARIA semantics removed, all its direct ancestor table elements will lose their implicit ARIA semantics as well. This is the primary exception to
role=none otherwise not negating the ARIA semantics of its descendant elements.
<table role=none> <tr> <!-- no longer a 'row' --> <td> <!-- no longer a 'cell' --> <table> <!-- this IS still a table --> <!-- also, gross. nested tables --> </table> </td> ... </tr> ... </table>
Alternatively, the use of
The following markup demonstrates an unordered list containing skip links to different sections of the unmodified web page.
<ul> <li><a href="#panel_1">...</a></li> <li><a href="#panel_2">...</a></li> <li><a href="#panel_3">...</a></li> </ul>
This pattern can be enhanced using ARIA to create a
tablist, but a
tablist expects a direct owning relationship with its
<li> elements would not be expected, and could cause issues in the way the pattern was communicated to assistive technologies. For instances like these,
role=none could be added to the
<li> elements to suppress the unwanted semantics.
<ul role="tablist"> <li role="none"> <a href="#panel_1" role="tab" aria-selected="true/false" aria-controls="panel_1"> ... </a> </li> <!-- etc. --> </ul>
With the semantics of the
<li> suppressed, the
tabs are exposed to the accessibility API in the expected format for a
Inappropriate use of
The following are two examples of common misuse of these ARIA features.
Use on focusable elements
One thing that these two features of ARIA share is that neither of them are meant to be used on interactive elements, unless very strict conditions are met.
For instance, is using
aria-hidden=true on a
<button> element, that element will still be keyboard focusable and browsers and assistive technologies are likely to correct author misuse by exposing the element when focused. Focusing could be by either keyboard focus, programmatic focus, or focus via a pointer event (mouse click or touch).
presentation, these roles are to be purposefully ignored under certain conditions, including if used on interactive elements that can be focusable, or have other global ARIA attributes.
In many cases, if you are trying to hide or suppress the semantics of an interactive element, then you may be in a situation where you should rethink your use of the element and these features. Otherwise, the only way to be absolutely sure that the element will be truly hidden, or its semantics suppressed would be to ensure the element was disabled as well:
<button disabled aria-hidden=true>...</button> <button disabled role=presentation>...</button>
disabled attribute fully removes the abillity for the
<button> element to be focused, browser mechanisms to error correct for the use of these attributes on a focusable element won’t run. Caution, you may create other accessibility issues – such as color contrast failures – if using these features in this way. But, that’s not what this post is about… I’m sure you’ll figure it out though. ;)
Another common mistake made by developers is using
aria-hidden=true together on the same element. For instance:
<element role=none aria-hidden=true> ... </element>
As has been described in this post,
role=none suppresses the implicit ARIA semantics of the element.
aria-hidden=true completely hides the element from the browser’s accessibility tree. If the element is completely hidden, then there’s no reason to supppress its semantics as well.
ARIA can be incredibly helpful in making document and interfaces accessible, especially when filling in semantic gaps of native HTML. However, it must be mentioned time and time again that no ARIA is better than bad ARIA.
If you’re going to use ARIA to augment your HTML, it should be done only when necessary. For instance, instead of negating the semantics of misused HTML elements – use the correct HTML element instead, or use a
<div> if you need a truly generic container.
If needing to markup an
<img> as decorative, provide it an empty
alt attribute. You likely do not need
aria-hidden=true for that.
Sometimes it may just take a quick step back to think about what it is you’re trying to accomplish. For more information on how hide content for all users, check out my previous article, “Inclusively Hidden”.