Accessibility considerations: Hidden content and the accessibility tree

Overview

Often when developing a web page, it can make sense to hide specific aspects of the page until a certain action occurs, which causes them to appear. A common example of this is navigation menus, which when navigated to sometimes display child items of the navigation menu in a list. The child elements of the navigation menu are often styled using CSS to be hidden by default, then shown when interacted with by using Javascript. Basic stuff, right? In the following post I’d like to explain the common pitfalls with hidden content and how it interacts with the accessibility tree. No idea what the accessibility tree is? Don’t worry, we’ll cover that too.

The Document Object Model and the Accessibility Tree

The Document Object Model (DOM) is what it says on the tin, a method to gather up information processed in the page source, and provide it in an object model, which can be interacted with and programmatically manipulated. For example, one of the most used commands in Javascript is document.getElementById which directly accesses the DOM to allow the user to reference an element, and with further logic be able to manipulate its attributes, styling and more.

The Accessibility Tree is a subset of the DOM, that mirrors each element included in the DOM, but strips out the unneeded parts which wouldn’t be beneficial for assistive technologies. In short, this is what is presented to assistive technologies who want to digest and interact with a web page.

It is important to understand that how each browser builds its DOM and Accessibility Tree will be different. Also their support for newer markup such as HTML5 and WAI-ARIA might be limited. That is why it is important to test what you plan to implement with various browsers and assistive tech.

Understanding the DOM and Accessibility Tree doesn’t really matter, but being able to identify why something may, or may not be picked by assistive tech does.

Hiding content from the Accessibility Tree with CSS

Using CSS we can hide an element from the page using either display: none;, or visibility: hidden;.

Although other methods of hiding elements with CSS exist, both of the above CSS properties are most commonly used. They have one common problem: both are completely ignored by assistive technologies! Now the fact that they are ignored is not a bad thing, but it does lead to misuse, which in turn creates accessibility problems.

So let’s look at some examples of where it could go wrong.

Hidden form labels

JD Sports have many flaws with their website, but let’s only consider their search field for now.

Labelless input field example.
Example of a labelless search input field, used on the JD Sports website.

Labelless search fields are quite common these days. They can impact accessibility in a few ways, but let’s just consider one: a field without a label. Now for assistive technology this creates a problem as the field will make no sense. For most it will simply be interpreted as an edit field. So to counter this we would add a label for the input field, to explain its purpose to assistive technology.

For purely the label aspect JD Sports do a couple of things wrong:

1. They correctly create a label for the input field, but don’t relate it to the field by using the label for attribute.

Incorrect:

<label>Search site</label>

Correct:

<label for="ID">Search site</label>

2. The input field for the search field also doesn’t have an ID attribute to map the label for to.

Incorrect:

<input name="freeText" type="text" />

Correct:

<input id="search" name="freeText" type="text" />

3. The final nail in the coffin though, and the one that we care about most in the context of this discussion, is their use of display: none on the search label.

I see this a lot! It drives me nutz, because knowingly, or not it defeats the purpose of the accessibility feature they have attempted to add. Of course though, not everyone understands that display: none;, or visibility: hidden; are ignored by assistive tech. In the case of JD Sports though, however had built their site is clearly a bit of a cowboy, who doesn’t really know what they’re doing.

So if you can’t hide it with display: none, or visibility: hidden then what do you do?

Display accessible content off screen

Well you can of course display it off screen, so that it is visually hidden, but can still be picked up by assistive tech. So in the case of JD Sports it would be something like so:

HTML

<label class="hidden" for="search">Search site</label>

CSS

.hidden {
position:absolute;
left:-10000px;}

Now this is my prefered method, but as Jonathan Snook correctly points out in his article hiding content for accessibility, this won’t work cosmetically for right to left languages. If you don’t have to concern yourself with RTL languages, then don’t worry. Otherwise use his suggested solution below:

CSS

.hidden {
position: absolute !important;
height: 1px; width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
}

Hidden navigation menus

Ok simple stuff, right? So what if we go for something a little bigger, like a navigation menu?

On the Poundland website, and countless others, they use display:none; to hide the contents of the drop down navigation menus until they are selected. Makes sense you would think. Let’s also assume that your dropdown navigation menu is keyboard accessible. It would still make sense, because when the user focuses on the top level navigation item, the child elements we assume will become unhidden? Wrong! We can’t predict that all users will interact with a web page in the same way. Keyboard navigation may be one choice – another option though might be to scan the page line by line with assistive tech, or use keyboard shortcuts to get where you want in a document before scanning its contents. This scenario wouldn’t work, as the child navigation items would be hidden from assistive techs view, so they would only pick up on the top level navigation items, not the hidden contents.

Poundland main navigation menu example.
Example of Poundland hiding content from users of assistive tech, with display:none;.

Again an off left technique would work fine here, which can be toggled using JavaScript to appear back on screen when in focus. The rule of thumb for elements which can be navigated to using the tab key, is to bring them back on screen when focused upon.

There are some scenarios where you may genuinely require an offscreen navigation element which would never appear on screen when in focus. The BBC for example use an accessible skip link, for users to skip the navigation and go straight to content. Their implementation jumps to an off screen navigation link, which is excluded from normal keyboard navigation by setting the elements tabindex attribute to -1 (exclude from tab order), but still focusable by setting focus using JavaScript.

SEO and CSS off screen techniques

Now hiding content off screen for accessibility purposes is all good, but couldn’t that be abused to improve search engine rankings? Of course it could, but thankfully search engines are clever enough to know when someone is abusing this or not. Keyword spamming off screen might downgrade your ranking, and if bad enough remove you from search listings altogether, but providing accessible information and links will not.

Google Webmaster Tools, have an article explaining this in their help sections, titled: Hidden text and links.

Putting display: none;, or visibility:hidden; to good use

So when does it make sense to use display: none;, or visibility: hidden;?

Well most sites in the UK now have a cookie policy message which appears the first time you visit a website. This is now a legal obligation which sites have to make you aware of, they don’t require you to accept it, they just need to present it to you on your first visit.

The Scottish Government has an odd example which admittedly isn’t fully accessible in its current implementation, but makes a good use case for using display:none; (and it does).

Scottish goverment website example of using display:none.
Scottish goverment website example of using display:none;.

After you have seen this cookie policy once, you’ll not need to see it again. Likewise for assistive tech, if you’ve read it once, you can effectively ignore it. Making use of display:none; here to hide the entire element that contains the cookie policy, allows assistive tech to effectively never process it again. Next time you visit the site, the div (element) that contains the cookies policy popup will be hidden using display:none;. This means that users of assistive tech do not need to process it again. If they styled it to appear off screen like we’d suggested for the previous examples, then visually normal users wouldn’t have seen it, but assistive tech would have still picked up on it.

Play around with the Scottish Government example and see if you can spot their accessibility mistakes with this cookie control. There is also a blatant lie in regards to cookies. See if you can spot it. No prizes, but I’m keen to see if anyone can spot the mistakes. Using what you’ve learned so far you should be able to.

A checkout process might be another example of when it might make sense to use display: none;. You might require data to be entered into the current step, before being able to progress to the next. So if you didn’t use display:none; here, then you might confuse users of assistive tech who would be able to read steps that visual users can’t, for good reason.

Other problematic CSS

VoiceOver by Apple has accessibility issues when an element’s height or width is set to zero. An element with this style applied will be ignored. Enrique Palazzo as far as I can tell was the first person to identify this issue on a Drupal issue ticket.

Kent County Council at the time of writing introduce this issue for VoiceOver users on their off screen skip links.

Example of the Kent council website impacting Voiceover users.
Example of Kent councils websites, impacting Voiceover users, with a height and width of zero.

It is easily fixed though by increasing the width and height to 1px.

While we are on the topic of faulty skip links, the UK Government’s Digital Service website hide their skip link with display:none;. Interesting when it is supposed to be a pioneer for government digital content.

Skip link example hidden using display:none.
Example of the UK goverments Digital Service website, hiding their skip link with display:none;.

So using CSS to hide elements from the page isn’t a terrible thing to do in regards to accessibility. The main problem is the misuse of it, and being able to understand when it should, or shouldn’t be used.

Problematic JavaScript

Everybody and their mom these days uses JQuery. Why? Well it’s a lot simpler to do things in JQuery than it is in JavaScript.

JQuery has a lot of methods that present accessibility issues if misused:

.hide()
.fadeOut()
.fadeToggle()
.slideToggle()
.slideUp()
.toggle()

Each of these adds display:none; inline to the element, which depending upon the context of its usage, could present accessibility issues. So when using any of these methods, like in our previous CSS examples, it would only makes sense to use them, if the context of there useage doesn’t impact accessibility.

JQuery also gives you a few DOM manipulation techniques, that obviously affect the Accessibility Tree:

.detach()
.remove()

There are others, but these are the two most commonly used. The main difference between the two is that .detach() will allow you to bring the element back into the DOM, .remove() won’t. Again use with caution. In the case of a cookie policy message that is only ever viewed once by the user, either of these might be a good option.

Another problem comes from inaccessible JavaScript methods for adding content:

write()
innerHTML()

The problem with both, is that they don’t interact with the DOM. As such elements added via these methods most likely will be ignored by all assistive tech. So avoid these like the plague!

Build a bear is one of my daughters favourite shops. They commit a double crime, with their flash not enabled warning. Firstly they exclude it from assistive tech as the write() method isn’t interacting with the DOM. Next they write in an image, with no alternative description. So they may as well display nothing, for all the use it provides to assistive technologies.

Build a bear no flash warning example.
Example of the Build a bear websites, no flash warning.

Obviously analysing Javascript adds a little more complexity onto your testing efforts. The most obvious way to test this, is to use some assistive technology to interact with the page, and see what is being picked up, or not. Personally I prefer to do some quick tests in developer tools, by inspecting inline and external JavaScript and searching (CTRL + F) for problematic methods, to see what they are doing. This way you can quickly identify where on pages they’ll be used, and test to confirm your suspicions with assistive tech.

Hiding content with HTML

There is a couple of attributes in HTML that can hide content from assistive tech.

Hidden input fields

The first is the input element’s type attribute. If the value of its attribute is set to hidden then obviously the field will be hidden from view. Assistive tech treats it exactly the same by ignoring it.

HTML

<input name="Language" type="hidden" value="English" />

It is actually quite a common technique, that is used on most websites, to store values. Back in the days of caveman development, when entire websites used to be constructed of forms to control layout, you could often see username and passwords being submitted in hidden fields as a form of access control. Thankfully those days are long gone.

So this technique isn’t so bad, depending upon how you use it. It’s pretty hard to mess this one up.

Alt tag

As a general rule of thumb if an image adds descriptive value to the context of a page, then add alternative text for it using the alt attribute. If it is purely for decoration, add the alt attribute but leave it empty.

HTML

<img src="randompicture.png" alt="" width="150" height="10" />

The above randompicture.png image if used purely for decorative purposes, would correctly have a null alt attribute value. Many assistive technologies will choose to ignore the element completely, as with an empty alt description, they assume it is for decorative purposes.

You might also add an image on a button with the type image, or a link anchor with an image inside it.

HTML

<a href="register.aspx">
<img class="overlaybtn" src="register.png" alt="" width="32" height="12" />Register</a>

In the above example you might confuse the need for adding alt text if the image overlaps the anchors link description. As the anchor already has a link description “Register” adding the alt of “Register” again would merely duplicate the content. For most assistive tech, duplicate content would be read twice, sometimes without any context, e.g. image alt: register, register link, might simply be processed as register, register link.

So it’s worthwhile noting that alt attributes with a empty value will be ignored by assistive technologies. Let’s not talk another further about the specifics of alt attributes and how to use them correctly, because that is a topic for another time, and already covered in great detail all over the web.

HTML5 hidden attribute

HTML5 brought us a new attribute called hidden, which when used hides the element it has been applied to from view.

As far as I could tell, all current browsers that support this attribute, simply apply a style of display:none; to the element. So effectively when used this will be ignored by screen readers, so use with care. As we have already discussed with the CSS technique, sometimes it is useful to use display:none; and other times it can impact accessibility.

Currently the way that browsers are treating this attribute, by applying a style of display:none; to it, for me seems pointless. CSS was of course created for this purpose: controlling presentation of the page. So I would argue that creating an attribute to control something that is already done via CSS, is pointless.

This attribute would be much better served by automatically applying the clip technique and assign on page generation a tabindex attribute to the element, with a value of -1.:

CSS

.hidden {
position: absolute !important;
height: 1px; width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
}

HTML

<a tabindex="-1" href="#maincontent">Skip to content</a>

At least now it can be used by assistive technologies in conjunction with aria-hidden to provide content for assistive technologies. Currently though what it does, is completely redundant.

Of course though, we could just live with it and think semantically that yes, perhaps hidden is indeed hidden, and as such display:none; would make sense. You can flip a coin both ways I guess, so who am I to argue?

Hiding content from the Accessibility Tree with WAI-ARIA

WAI-ARIA introduces a couple of ways to hide content from assistive technologies.

The aria-hidden attribute

Sometimes it might make sense to hide visual content from assistive technologies. To do this we make use of the aria-hidden attribute. If you are displaying duplicate content because it fits with the design, rather than having the content interpreted twice by a users of assistive tech, you can hide the most sensible instance using aria-hidden.

HTML

<img src="decorative.png" alt="" aria-hidden="true" />

In the above example HTML it might even make sense to use aria-hidden to make sure decorative images are not read out by assistive technology. Although some assistive tech will ignore images with empty alt tags, not all will, so doubling up with aria-hidden=”true” helps our chances. I say chance, because support in both assistive technologies and browsers is a bit lacking.

Presentation role

The presentation role, is used to convey that an element is used for presentational purposes only. As such, these elements would provide no benefit to users of assistive technologies and should therefore be ignored.

HTML

<img src="decorative.png" alt="" aria-hidden="true" role="presentation" />

Again using the same example as used in the aria-hidden example, specifying an element with the presentation role, further increases our chances of it being ignored by assistive tech, but still having it remain visually on screen.

Specification example use cases:
1. An element whose content is completely presentational (like a spacer image, decorative graphic, or clearing element);
1. An image that is in a container with the img role and where the full text alternative is available and is marked up with aria-labelledby and (if needed) aria-describedby;
2. An element used as an additional markup “hook” for CSS; or
3. A layout table and/or any of its associated rows, cells, etc.

So useful, but again lacking real support from browsers and assistive technologies.

Summary

So I hope you are now more aware of how elements can be intentionally, or unintentionally hidden from assistive technologies. There is a lot to consider, but the most important aspect, is to consider the context of the element/container in question before deciding if the technique is correct, or not.

Thanks for reading.

Related posts:

  1. Accessibility considerations: Logical document structures
  2. Accessibility considerations: Visual indicators for keyboard navigation
  3. Considerations for accessible web development
  4. Accessibility: The perils of ignorance.
  5. Accessibility: Pairing with a blind consultant.