Why “left: -9999px;” is Better For Accessibility Than “display: none;”


Update: Thierry Koblentz points out in the comments that either technique may be appropriate, depending on circumstances. I mention this in the last paragraph, but just to be clear, there should have been a “usually” or “often” or some such word in front of the “better” of the title. That, or a different title.

Update 2, December 2008: It is now accepted that it is better to use top: -9999px;, as using left: would cause a scroll bar on a page with right-to-left text.

A recurring question on various mailing lists such as the Web Standards Group discussion list is “How can I hide content but still have it accessible?” This is usually asked in the context of image replacement techniques, where one might for example wish to display a heading in a fancy typeface, but still have the content accessible to users of assistive technologies such as screen reading software.

Two techniques, both reliant on CSS, tend to come up in these discussions: hiding the text by the use of display: none or visibility: hidden, and positioning the text off-screen, using absolute positioning and left: -9999px, or margin-left: -9999px.

Access Matters determined back in June 2005 that the display and visibility techniques appeared to be inaccessible to screen readers, whereas the offscreen positioning method was accessible. The full results go into more detail.

One thing that nobody seemed to have bothered to explain was just why this was the case. Inspired by yet another thread on the subject, I finally decided to do some digging; if I don’t know why I’m doing something, I can’t be sure that I should be doing it, which leads to the risk of Cargo Cult coding.

Ask the people who know

To my astonishment, a search of the Microsoft Developer Network Library quickly brought me to the explanation I sought. (I was astonished because the MSDN library search is notorious for returning swathes of irrelevant results for even the simplest search; I have heard anecdotal evidence that Microsoft’s own developers search the library using Google with the site:msdn.microsoft.com specifier.)

The library’s section on accessibility support in Internet Explorer is extensive, but the information about invisible objects told me all I needed to know. To quote:

With Internet Explorer 6 and later, the pvarState parameter of the IAccessible::get_accState property receives STATE_SYSTEM_OFFSCREEN when the object is invisible because of scrolling and receives STATE_SYSTEM_INVISIBLE when the object is invisible because its IHTMLStyle::visibility property is set to hidden, or its IHTMLStyle::display property is set to none.

Again, in English?

A screen reader doesn’t load an HTML page: the browser (usually Internet Explorer) does that. What the screen reader does is to ask IE about the content, using an API called Microsoft Active Accessibility (MSAA). MSAA allows the screen reader to interrogate the browser as to the contents of a page; the dialog, insofar as I understand it, would go something like:

Internet Explorer:
Hey, I’ve just loaded a page.
Screen reader:
Cool, what’s it got on it?
Internet Explorer:
There’s a heading, then some links, then a few paragraphs.
Screen reader:
OK; give us the heading.
Internet Explorer:
It says “Welcome to HyperGlobalMegaCorp”.
Screen reader:
Right, hang on a moment. (Speaks the given text to the user.)

… and so on; you get the general idea.

The key is that IE doesn’t just return content to be spoken in some way; it also returns information about that content. This includes information that goes by the snappy name of pvarState, and one of the aspects of this information is that it can tell the screen reader whether or not the content of the thing it’s asking about (for example, the heading in the above dialogue) is actually displayed on the screen – that is, whether it’s visible or invisible. (Note that these terms aren’t being used here in exactly the same way as they are in CSS.)

There are three ways that IE comes to regard something as being invisible:

  1. It has the CSS property display set to the value none;
  2. It has the CSS property visibility set to the value hidden;
  3. It is in a position where the window would need to be scrolled for it to become visible.

IE further distinguishes these three forms of invisibility by dividing them into two kinds. The first two forms of invisibility are denoted by the pvarState value STATE_SYSTEM_INVISIBLE, and the final form is denoted by the value STATE_SYSTEM_OFFSCREEN.

So finally it all becomes clear: screen readers will treat content with the state STATE_SYSTEM_OFFSCREEN as being content that it should read, because it’s only invisible by virtue of not being within the visible region of the window: after all, a screen reader that required the user to scroll the window to read all of the content would be of very little value to anybody. The only reason that the content can’t actually be scrolled into view when using the off-left or off-top positioning technique is that Internet Explorer itself doesn’t support the concept of scrolling the window by a negative amount, although I believe this isn’t a limitation of the Windows scrolling mechanism per se.

If, however, the screen reader finds that the state of the content is STATE_SYSTEM_INVISIBLE it apparently concludes that it must have been concealed for a reason, and doesn’t speak it.

So there you go: use one of the offscreen methods and the screen reader will treat your content as being there; use the display or visibility method and the screen reader will discard it, meaning that this is a reliable way of concealing content from both a normal user and a screen reader user, should you have a reason to do so. But armed with the information above, you’ll at least know why you’re using whichever method you apply.

This post is now available in Belorussian provided by http://www.fatcow.com/ – many thanks for that!


16 responses to “Why “left: -9999px;” is Better For Accessibility Than “display: none;””

  1. It’s a practice I use all the time except in the rare instance where I actually want something to be available when styles are off but not available to screen readers. Outstanding article, revealing the why behind it. I especially like the way you turned the negotiation between browser and screen reader into a conversation. Kudos.

  2. Good read. You may want to include a short comment saying that it is not *always* better for accessibility. I’m thinking of dropdown/flyout menus containing *many* links.
    This article [1] is about two type of dropdown menus, to hide sub-menus one uses “display:none” the other “position:absolute”:
    IMHO, going with “display:none” for this type of menus is Better for Accessibility.

    [1] http://www.tjkdesign.com/articles/Pure_CSS_Dropdown_Menus.asp

  3. Good point, Thierry; in the last paragraph I mention the fact that either technique may be appropriate, but I should have made it clearer. I’ve added a preamble pointing out that I really should write better titles 🙂

  4. I use the same technique for hiding input tags – if you leave it as display: none; then Safari will not send it when submitting the form!

    Good read!

  5. Thanks for this article. Most informative! I started off using display:none; wuite a bit when starting off in CSS but the left:-9999px; technique has recently become my preffered technique of hiding elements from view… and now i know WHY! 🙂 Keep up the good work my friend.

  6. I dont know if ive been doing it wrong, but i ofter use

    height:0;
    overflow:hidden;

    it seems to work in most of my testing browsers…

    Am i doing it wrong?

  7. Cole: If I understand the Microsoft documentation correctly, it’s only the display and visibility properties that will result in the item being treated as invisible. There is a mention of checking for iframes being of zero height or width, but it seems that this is a special case that authors of assistive software deal with in whatever way they think best.

    Therefore, it’s down to what screen reading software actually does; the documentation doesn’t seem to make any specific recommendation. If anybody has done any tests on this, perhaps they could be kind enough to post a link here.

  8. One problem I have found with offscreen positioning is that form elements seem to choke on the technique in JAWS (v8). I have also tested in Window-Eyes (v6) which seems fine. I would be interested to know if anyone else has had a problem with this in other versions of JAWS or other screen readers.

  9. […] One of the most valuable tools in a web designers arsenal is the ability to replace text with images, of course in a graceful way. That technique is exactly what makes the CSS Zen Garden layouts work. Thanks to NickFitz we now know the right way to do this (and why the wrong way may sometimes be right). Read his excellent article Why “left: -9999px;” is Better For Accessibility Than “display: none;”. […]

  10. Nick – thanks for taking the time to de-scramble the MSDN explanation so it makes sense to laymen like myself.

    I’m personally fond of the empty span within the hyperlink or heading for image replacement.

    The one benefit over moving things off-screen is the instance where the user has a qualified browser, but for some reason has images turned off. The hidden text remains in place.

    No method is without its downfall on some level.

  11. […] Topsy Retweet Button var topsy_style = “small”; var topsy_order = “count,retweet,badge”; var topsy_url = “http://www.nickfitz.co.uk/2007/02/14/why-left-9999px-is-better-for-accessibility-than-display-none/”; Add Topsy Retweet Button to your Blog or Web Site. WordPress  Web Sites […]