Latest Update: The state of hidden content support in 2016
As a developer and also a consultant advising developers on how to develop accessible content, it is important to have and provide up to date and practical knowledge about robust development techniques. A recent question on Stack Overflow got me thinking: What is the best method for hiding content for all users? For hiding content for some users?
The standard technique for hiding content for all users has been the use CSS display:none
. Now, both ARIA and HTML5 also provide a semantic indication of content state that indicates content is hidden or should not be available to users:
HTML5 hidden
The HTML5 hidden
attribute provides a semantic indicator:
All HTML elements may have the
hidden
content attribute set. Thehidden
attribute is a boolean attribute. When specified on an element, it indicates that the element is not yet, or is no longer, relevant. User agents should not render elements that have thehidden
attribute specified.
Example code:
<p hidden>This content is hidden.</p>
HTML5 hidden effects:
- In supporting browsers the content is not displayed to any user.
- semantic indicator of state in HTML code (
hidden
attribute) - CSS style of
display:none
applied by browser. - Focusable content is not included in tab order.
- Not included in the accessibility tree.
aria-hidden
Indicates that the element and all of its descendants are not visible or perceivable to any user as implemented by the author.
Example code:
<p aria-hidden="true">This content is hidden.</p> <p aria-hidden="false">This content is not hidden.</p> <!-- aria-hidden="false" is same as --> <p aria-hidden="true">This content is hidden.</p> <p>This content is not hidden.</p>
aria-hidden
effects:
- In supporting browsers in conjunction with supporting assistive technology the content is not conveyed to the user via the assistive technology.
- Content is displayed in the browser.
- semantic indicator of state in HTML code (
aria-hidden
attribute) - In some browsers its not included in the accessibility tree in other browsers it is included in the accessibility tree.
- For browser that include
aria-hidden
content in the accessibility tree focusable content is included in tab order and is navigable and operable for AT users (as well as other users).
- For browser that include
- In browsers that do include the content in the accessibility tree the content has an accessible MSAA (if supported) state of
invisible
. If IA2 is supportedaria-hidden=true
is passed as an object attribute. If UIA is supportedaria-hidden=true
is passed as an ARIA property. aria-hidden=false
is not mapped in any browser that supports aria-hidden, thus its use has no meaning or in other words has the same meaning as its absence.
CSS display:none
As mentioned, the standard method to hide content from all users in browsers that support CSS is and has been to use CSS display:none
.
Example code:
<p style="display:none">This content is hidden.</p>
display:none
effects:
- In supporting browsers the content is not displayed to any user.
- Focusable content is not included in tab order.
- Not included in the accessibility tree (except for IE)
- In IE the content has an accessible MSAA (if supported) state of
invisible
. If UIA is supportedOffScreen=true
.
Recommendations:
Hiding content from all users
If you want to hide content from all users, use the HTML5 hidden
attribute (along with CSS display:none
for browsers that do not yet support hidden) There is no need to use aria-hidden.
Example code:
.hidden {display:none} <p hidden class="hidden">this content is hidden from all users</p>
Hiding non interactive content from visible display
Use an off screen technique to remove content from visible display, but still available to screen reader users:
Example code:
.offscreen { clip-path: inset(100%); clip: rect(1px, 1px, 1px, 1px); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; /* added line */ width: 1px; } <div class="offscreen">This text is visually hidden.</div>
Modified example code from: WebAIM – CSS in Action: Invisible Content Just for Screen Reader Users
Updated code examples, October 2016, to take into account new advice from Jessica Beach: Beware smushed off-screen accessible text
Hiding interactive content from visible display
Hiding interactive (focusable) content from visible display using the off screen technique means it is not visible, but still in the tab order and causes issues for keyboard only users. Focusable content should only be hidden from visible display if the focusable element becomes visible when it receives focus:
Example code:
a.offscreen { clip: rect(1px, 1px, 1px, 1px); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; /* added line */ width: 1px; } a.offscreen:focus { position:relative; clip:auto; width:auto; height:auto; overflow:auto; } <a class="offscreen" href="test.html">this link is offscreen unless it has focus</a>
Notes by Ted Drake, on use of the off screen technique described:
Using negative position can create long scroll bars when localizing a site for a rtl language. Also, it uses CSS properties that are commonly used and easy to accidentally over-ride.
The Yahoo Accessibility Lab recommends using clip for content that should be hidden from the visual user, yet available to screen reader users. Thierry Koblentz has a great article on this technique, as well as the underlying philosophy behind using the correct CSS techniques for hiding content. Clip your hidden content for better accessibility
The tests
Support for aria-hidden
, HTML5 hidden
and the off screen technique was tested using JAWS, Window Eyes and NVDA (Windows), ChromeVox (Chrome OS), VoiceOver (iOS and Mac OSX) and Orca (Linux) with supporting browsers for each OS.
Result summary
- Use of HTML5
hidden
(+ CSSdisplay:none
) worked in all screen reader/browser combinations tested. - Use of the off screen technique worked in all screen reader/browser combinations tested.
- Use of
aria-hidden=true
worked in some screen reader/browser combinations tested. - Use of
aria-hidden=false
had no effect in any of the screen reader/browser combinations tested. In other words if content is hidden from all users using HTML5hidden
ordisplay:none
applyingaria-hidden=false
to the content does not make it visible to screen reader users.
Detailed tests and test results are available -updated 11/2013.
Comments
Did you happen to test HTML5 hidden alone? I would think that using it alone should be the ultimate goal, once it has sufficient support. And I’d also think that support should be entirely browser-specific (screen readers shouldn’t need to do anything special if browsers hide the content correctly), right?
Of note with aria-hidden=”false” is the the false assumption that you can use it unhide portions of content within something that is hidden (e.g., embedding aria-hidden=”false” content within a larger aria-hidden=”true” element).
Great post!
Hi Jared,
HTML5 hidden alone is test 2. I have only advised to use in conjunction with display:none until IE starts supporting it. Note that hidden is implemented in browsers by applying display:none to the hidden content.
Agreed.
This is the false assumption I have attempted to debunk.
Hi Steve
Using negative position can create long scroll bars when localizing a site for a rtl language. Also, it uses CSS properties that are commonly used and easy to accidentally over-ride.
The Yahoo Accessibility Lab recommends using clip for content that should be hidden from the visual user, yet available to screen reader users. Thierry Koblentz has a great article on this technique, as well as the underlying philosophy behind using the correct CSS techniques for hiding content. Clip your hidden content for better accessibility
thanks for the info Ted, will test and update the advice as appropriate!
position: absolute also prevents many popular JavaScript effects (jQuery, Prototype etc.) from working. At the time of this writing, JavaScript libraries heavily rely on display: none to create animations such as fadeIn(), fadeOut(), show(), hide(), slideUp(), slideDown(), animate() (and similar, in libraries other than jQuery). I think that many web developers will continue to use display: none also in the future. The point is that this declaration belongs to the
screen
media, not thespeech
one. If a screen reader interprets a declaration which has nothing to do with its media, this cannot be set as a rule to avoid this declaration.Another option is to use text-indent to hide the text if you don’t want users to see it. Zeldman had an article on this in early March, but the summation is code like the following:
.hide-text {
text-indent: 100%;
white-space: nowrap;
overflow: hidden;
}
I’ve found it useful in most situations, especially when dealing with i18n and the rtl readers.
Hi Gabriele,
I am missing your point, what exactly are you objecting to?
In my view, you create some false impressions:
FIRSTLY: Regarding @aria-hidden=false, the test result table indicates that test 5 and 6 Fail in all browsers. But, in reality, it is NOT a Fail – but a Pass, since it works as intended. That some might have an incorrect impression of how it is supposed to work, is a separate issue.
SECONDLY: You claim that @hiddden works in all browses. But actually – like you also admits – it requires display:none, to work in IE. This has implications for how you portray @aria-hidden=true, see below.
THIRDLY: What you say about @hidden, casts doubs about @aria-hidden=true. Fact is that, as long as the author adds display:none, then @aria-hidden=true works just as well as @hidden. And, fact is also, that ARIA RECOMMENDS to @aria-hidden=true with display:none: [aria-hidden=true]{display:none}
FOURTHLY: For the use case that something should ONLY be hidden for screen readers, then @aria-hidden=true is the only option. However, you fail to make any positive remarks about this advantage …
So — it seems like you are a little bit too eager to portray @aria-hidden negatively. ;-D
Hi Leif,
I am eager to find the most robust method of hiding content from users.
aria-hidden
has no advantages over HTML5hidden
for this task. So why promote its use.What I am attempting to do there is drive home the the incorrectness of the impression that some developers appear to have i.e.
aria-hidden=false
actually does something.Hidden is supported by current versions of Firefox, Chrome, Opera and Safari on multiple platforms. As noted IE 9 does not support hidden, it has been reported that IE 10 does.
HTML5 hidden is simpler and when fully implemented will not require authors adding a CSS style, the same cannot be said for aria-hidden, so there is no advantage to using aria-hidden for the use cases outlined.
It’s a rare use case, the much more common uses cases are the subject matter for this article.
In Drupal 7 and 8 development we have struggled with this same question. We ended up with a combination of the Clip technique along with the width:1px, height:1px.
Here is a blog post about our thought process: https://adaptivethemes.com/using-css-clip-as-an-accessible-method-of-hiding-content
Other resources:
https://snook.ca/archives/html_and_css/hiding-content-for-accessibility
https://webaim.org/techniques/css/invisiblecontent/
This brings up a quick question, where it states
“Use of HTML5 hidden (+ CSS display:none) worked in all screen reader/browser combinations tested.”
Is there any reason why display:none couldn’t be used by itself to accomplish the same result?
The instructions imply that, only through a combination of both HTML5 and CSS, can content be properly hidden in a cross-browser compatible manner, but I’ve never heard of a circumstance where display:none fails to hide content appropriately. If there is, it would be great to know.
Plus, for dynamic applications, if you want to make a previously hidden element visible, you would have to change both the CSS and remove the ‘hidden’ attribute from the tag, otherwise content may be hidden for some and not for others.
Also, just as an FYI, when in Forms Mode in JAWS (such as when Auto Forms Mode is off), the following is announced every time you tab to another form field in the Comments form:
“how to remove CSS outlines in an accessible manner? HTML5 Accessibility Chops: hidden and aria-hidden Posted on May 1, 2012 by Steve Faulkner As a developer and also a consultant advising developers on how to develop accessible content, it is important”
At least using JAWS12 and IE8. This appears to result from the use of role=main within one of the parent tags. Removing this from the DOM fixes the problem.
Sincerely,
Bryan Garaventa
Hy Bryan,
As indicated in the testing results display:none on its own works in all browser/AT combinations tested.
The reason for using an attribute in the DOM to provide provide a semantic indicator of state is detailed in the ARIA spec:
Same goes for HTML information in general. Use of
display:none
in isolation does not provide such an indication.Plus, for dynamic applications, if you want to make a previously hidden element visible, you would have to change both the CSS and remove the ‘hidden’ attribute from the tag, otherwise content may be hidden for some and not for others.
For browsers that support the hidden attribute, adding it applies the CSS
display:none
automatically (content is not visible to any user) and removing it makes content visible to any user. If only hidden is removed the content will still be hidden for all users as the CSS rule will still be in place. If only the CSS rule is removed then the content will be available to IE users, but hidden for users of other browsers. That would result in a general authoring bug, not a specific accessibility bug and should be picked up by an developer worth their salt as the page will not work as expected in IE.Also, just as an FYI, when in Forms Mode in JAWS (such as when Auto Forms Mode is off), the following is announced every time you tab to another form field in the Comments form:
“how to remove CSS outlines in an accessible manner? HTML5 Accessibility Chops: hidden and aria-hidden Posted on May 1, 2012 by Steve Faulkner As a developer and also a consultant advising developers on how to develop accessible content, it is important”
At least using JAWS12 and IE8. This appears to result from the use of role=main within one of the parent tags. Removing this from the DOM fixes the problem.
Thanks for pointing this out, I will attempt to fix it. JAWS has some bugs in regards to landmark roles.
Hi Brandon, thanks for the info!
Hi Bryan, think the issue is fixed now, added a role=form landmark to the from element.
Excellent, that does fix the form field tabbing issue 🙂
I understand what you mean about the HTML5 spec, but how does this fit in with proper XHTML syntax? For example, to validate properly, it would need to be written as hidden=”hidden”. Would this break the functionality if proper standards are observed?
Hi Bryan,
The only thing that breaks if
hidden
is used with a non HTML5 doctype is the HTML validator (in that it emits validation errors). Browsers do not care what DOCTYPE an author uses as long as the DOCTYPE does not trigger quirks mode. For example I have created a test page with the XHTML strict doctype, it contains a singleP
element with ahidden
attribute. It works as expected in supporting browsers, but use of hidden is shown as an error when validated.I really Agree with 4th Point; I think ARIA is fantastic. I was working on a PhoneGap app an needed iOS Safari VO not to read a component EXPRESSLY for visual effects but doesn’t need read for those using VO. An I’m sure there’s some crazy reason you use the
display:none
stuff an what not but I don’t know what it would be..Oh wait!! I didn’t even use
aria-hidden
junk in mine I went back an noticed I usedrole="presentation"
… which did the same thing.. Maybe worth mentioning. I’m sure I tried the other but I must have fun into some probelms using it. Can’t remember what exactly.Hi David,
First off I am a proponent of WAI-ARIA when useful.
role=presentation
is different, it will remove the semanics of an element, but not the text content.Example:
heading
Will result in the heading and its content being hidden from users of supporting browsers and AT.
heading
Will result the text “heading” still being available, but the heading semantic “H1” will be removed from the accessibility tree.
In the interest of completeness: there is one way to hide content from any user, which should be used if the content is never intended to be unhidden: the HTML comment. (Because nothing goes with out saying!)
Thanks Steve, Good to know. I”m trying to make my app as cross platform on iOS as possible before I move over to something more like Android etc. Found iOS 4.3.5 doesn’t support near the feature set that 5.1 does when it comes to ARIA. I’m an adhoc dev and I’m learning slowly all the lingo.
Hi George,
That technique is not that safe. See: Replacing the -9999px hack