Grow your CSS skills. Land your dream job.

Places It’s Tempting To Use Display: None; But Don’t

Published by Chris Coyier

You want to hide something on a page, so:

.hide {
   display: none;
}

But wait! By applying that class to an element you've immediately made that content "inaccessible" by screen readers. You've probably known this forever, but still the poison apple sneaks into our code once in a while.

I don't want to re-hash all the specifics. Your best bet is to read "Now You See Me" by Aaron Gustafson on A List Apart to get an understanding of this if you don't already.

One way to encourage yourself to do the right thing is by creating more appropriate class names. Your regular hide class should position the content off screen, which still leaves it screen reader accessible:

.hide {
   position: absolute !important;
   top: -9999px !important;
   left: -9999px !important;
}

I use !important here because if you've gone to the trouble to add a "hide" class to something, you probably mean it and don't want to think too hard about if the specificity value is strong enough. And if you know that you need to display: none something, the class should help you understand it:

.remember-this-will-NOT-be-read {
   display: none !important;
}

Another option for accessible hiding comes from some Snook research and the HTML5 boilerplate:

.visuallyhidden { 
  position: absolute; 
  overflow: hidden; 
  clip: rect(0 0 0 0); 
  height: 1px; width: 1px; 
  margin: -1px; padding: 0; border: 0; 
}

OK you got it. Easy peasy when you're totally in control of class names and all you do is apply and remove them. But things get a little tricker with JS libraries that apply their own CSS. For instance in jQuery, after you .slideUp(), you'll have a display: none in the inline CSS to deal with. Yes, screen readers run JavaScript and yes, that's still a problem.

Again Aaron Gustafson has us covered there, who suggests applying the accessible class name after the sliding is done and then removing the display: none by sliding it the other direction.

var $button = $('#myButton'),
    $text   = $('#myText'),
    visible = true;

$button.click(function() {
  if (visible) {
    $text.slideUp('fast',function() {
      $text.addClass('hide')
           .slideDown(0);
    });
  } else {
    $text.slideUp(0,function() {
      $text.removeClass('hide')
           .slideDown('fast');
    });
  }
  visible = !visible;
});​

Here's a demo of that:

View Demo

Now we have the tools we need to stop using display: none and start using more accessible "hiding" methods.


FAQ pages

If you're hiding the answer until the question is clicked, hide with an accessible class name. Careful you don't .hide() and then slideToggle(), that's not good enough!



Labels

It's tempting to use placeholder text as a label replacement (especially now with some browsers improved UX of leaving the text until you actually type), but don't display: none or remove the labels. I recently heard a heartbreaking story about a blind girl trying to apply for college and the form had missing labels so she had no idea what to put in what fields. So if you're going to use placeholder text as a label replacement, use an accessible hiding technique for the labels.



Tabs

Just because a panel of content isn't the "currently active" one doesn't mean it should be inaccessible. Hide it with an accessible hiding technique instead. Or, you may not even need to. If all the panels are the same height, you can just flip-flop which ones is visible by adjusting z-index.



@media queries

Turning on Voice Over in OS X and using Safari is a screen reader. Now imagine that Safari window was open to a very narrow width and the page had some @media queries for handling smaller viewports. And say that @media query hides some things with display: none in order to better visually accomodate the space. This could be good or bad for accessibility. Are you hiding a bunch of crap that isn't important to the page? Or are you hiding useful things that a person using a screen reader should have access to like they normally would.


No Expert Here

This entire post is based on the premise that display: none is bad for accessibility. It's not based on my deep and thorough understanding of screen readers and general accessibility. If you have more to add, things to correct, or personal experience to share, please do.

Comments

  1. Henrik
    Permalink to comment#

    I had no idea of this, great article!
    It’s too bad that things like placeholder aint implemented in the spec a better way, we’r lucky to have the gurus to point out this problem with a solution. I guess we’ll have to wait a long time before there will be a own css attribute for this, should be display: screenreader; or something.

  2. micah
    Permalink to comment#

    Too bad there isn’t some type of media query for screen readers where you can just switch those values to block.

  3. Permalink to comment#

    But display:none; is such a useful property!!!

    • Permalink to comment#

      Yes it is, no doubt! And that is the purpose of this article! To discuss the dark side of misusing it!

  4. Gijs
    Permalink to comment#

    Why would you hide things and still want them to be read? Sounds like a contradiction in terms to me.

    Regarding the tabs example, instead, why don’t you make sure the tabs are keyboard-accessible (so don’t just add a click handler, use/make focusable elements for the tabs, and add keyboard handlers for it, and check that your tab order is sensible). Add some WAI-ARIA roles and modern browsers and screenreaders should be able to use them just like sighted users would.

    This touches on a more important point: don’t assume ‘screenreader users’ and ‘normal users’ covers everyone. If you’re using hover only to hide/display content, you’re already doing it wrong (and how you hide the content is less important than making sure people without a mouse can unhide it).

    • Permalink to comment#

      I agree.
      What’s the purpose of hiding something but not really hiding ? I never see a screen reader and maybe there is a reason of this but for me the problem is more how to unhide something on screen reader

    • Ade
      Permalink to comment#

      Headings for major content sections to create a fuller heading hierarchy for non-ARIA-aware ATs, for example, Gijs?
      Skip links? (Though only on large screens should they ever be allowed off-screen.)
      To name just two.

      And Vexal, if you have never even seen a screen-reader (or, I assume any other AT), then you really need to try one. There is no excuse for any front-end developer not bothering to spend just a little time using NVDA, Orca, VoiceOver, or even an evaluation version of JAWS.

    • Dave
      Permalink to comment#

      “Why would you hide things and still want them to be read? Sounds like a contradiction in terms to me.”

      I’m guessing this is faux naivety to make a point?

      People hide things in interfaces so they can be shown as a result of some user interaction.

    • Gijs
      Permalink to comment#

      Ade: good examples. The rationale for those examples, however, is to have extra content for screenreader users which is hidden for normal users. That isn’t the case for the examples in the blogpost

      Dave: Faux naivety — no, serious question. If you’re hiding things to re-show after user interaction, then just make sure screenreader users can show them like anyone else. Most have JS support; if they do not, they should (for the purpose of these particular elements) be treated like anyone else with no JS, and the content should probably not have been hidden in the first place.

  5. Permalink to comment#

    another aspect of this is, that elements, to which display: none; is applied, are excluded from the dom- loading process.

    this is impractical, if one binds a load-event on a non-displayed inline-image or one wants to get the dimensions of an elemens, that isn’t displayed.

  6. Permalink to comment#

    Спасибо, очень интересный обзор, но из него вытекает немалый объем работы по переписыванию script`s и css`s.

    • Rasmus
      Permalink to comment#

      Exactly my thoughts!

    • Bert de Vries
      Permalink to comment#

      Google translation:

      Thank you, very interesting review, but it implies a considerable amount of work to rewrite the script `s and css` s.

  7. Permalink to comment#

    If you’re hiding text on an FAQ page with the intention of showing it with JS, you should also hide it with JS, otherwise, people using regular CSS enabled browsers but with JS disabled JS will never be able to see the text, leaving you with an unusable FAQ’s page!

    • a man
      Permalink to comment#

      Excellent point. Remove it (visually) once the DOM loads.

      Not to derail the discussion but why are one-liner comments so high in this site?

    • A nice option for this is to hide things that need to be hidden that way with CSS, but under a class set by js like:

      CSS:

      .js .visuallyHide {
      position: absolute;
      overflow: hidden;
      clip: rect(0 0 0 0);
      height: 1px; width: 1px;
      margin: -1px; padding: 0; border: 0;
      }


      JavaScript:
      $("html").addClass("js");

  8. Permalink to comment#

    Thank you, Chris, reads like this bring the web forward :-)
    Cheers!

  9. If you’re using less/sass you don’t even need to add to .hide (I use .hidden) class in the html, but you can use them as mixins. It saves you the trouble (and unpleasant feeling) of using !important and you don’t need back-end changes later on if the design changes.

    As for not tabs and keyboard access, this won’t really help out screenreader users. Display:none is bad practice, it’s a shame jQuery and others are so reliant on it.

    • Gijs
      Permalink to comment#

      What makes you think tab/keyboard access is of no help to screenreader users?

  10. Unfortunately this is a sad truth. Another sad fact is the lack of standard screen readers. For example label, even with display: none, it reads in Jaws (for windows). But it is a point to take care. Thanks

  11. Permalink to comment#

    Simple, direct and very enlightning! Thanks!

  12. Don’t make the possibly false assumption that screenreaders don’t ‘have’ javascript.

    There’s a chance that the screenreader is reading the screen over the top of the browser. It makes sense to hide something using display:none in that case (with javascript), as in your FAQ example.

    The browser can tab into the FAQ question, read it, then hit enter to open up and (and using #anchors) leap to the start of the answer. If they don’t want to see the answer, they’ll move on to the next question in the list, rather than having to read *all the questions* and *all the answers*, as would happen if the .hide answers are pushed off-screen.

    Note – if you really like, set the item to display:none by default, then immediately overwrite it in a file called e.g. noscript.css. Use javascript to remove the noscript.css file. This would avoid and display of all the open items, before js kicks in on DOM ready.

    • This is a great example of how thorny web development can be. You might spend your time ensuring that your content is accessible to screenreaders, just to make it annoying for those folks to actually interact with your site. I believe it was Roger Johansson (456 Berea St.) who pointed out that just because someone is using assistive technology doesn’t mean they don’t want to have the same browsing experience as everyone else.
      Personally, I use the .no-js / .js classes (w/Modernizr) to ensure my content is accessible to those without JS, while still providing a pleasant user experience to those with JS, and then I use .visuallyhidden classes for any “helper” text for screenreaders.

  13. Daflita
    Permalink to comment#

    In my case, hidden text is a useful tool to accessibility. Here in Brazil, screen-reader users appreciate when we tell them where they are and how that content is showing.

    For example:

    <aside>
         <p class="visuallyhidden">Column right of the content</p>
         <h2>Sidebar</h2>
    </aside>

    I normally use h5bp.com‘s visuallyhidden class to hide this kind of text because it is obvious to “normal” users and a welcome information to screen-reader users.

    PS: I’m still trying to figure out how this affects SEO though.

  14. MrFjords
    Permalink to comment#

    Great post. Just starting to learn about accessibility, so I found this very informative.

  15. Rather than setting your “hidden” class and executing the reverse of whichever jQuery animation got you a “display:none,” wouldn’t it be better/easier/more efficient to either just remove the style attribute or use the .show() method?

    • This is what I was going to ask. Why animate something that you’re not going to see animate? You could just use hide() and show(). I guess that if you were needing something that those don’t do, you could extend jquery and create something like: .readable() which set everything you needed set, without animating something you weren’t going to see change.

      Also, maybe you could update the way .animate() behaves at the top of your document, to accept a {readable: true} paramater? You could set it up to even be passed down from things like slideDown, allowing you to instantly cover accessibility.

  16. Thanks for including the examples, they were extremely helpful.

  17. joe
    Permalink to comment#

    I always thought that using CSS with top: -9999px; is bad SEO. Basically, spiders assume you’re hiding SEO’d content on your page but not wanting it viewed as part of the site. For example, you could throw a bunch of keywords in a div and hide it off the page. If the crawlers find a div positioned like this it’ll lower your ranking.

  18. I feel like the problem is more with screen readers and less with the way things have been designed to be coded…

    • Ade
      Permalink to comment#

      That’s a not-very-well considered comment. Screen-readers and most other ATs, are supposed to respect display:none (form mode excepted) because of its primary purpose. And besides that, ATs that rely on the accessibility layer are at the mercy of what is in that layer.

  19. Permalink to comment#

    Thanks for the post. Good information. Joe, I used to think that, but the key is your intent in hiding the text. Read what Google says about this on Google Webmaster Central.

    • joe
      Permalink to comment#

      The problem is how do Google crawlers define your intent? I wish that article you linked made it clearer. This is what it stated: “If your site is perceived to contain hidden text and links that are deceptive in intent, your site may be removed from the Google index, and will not appear in search results pages. When evaluating your site to see if it includes hidden text or links, look for anything that’s not easily viewable by visitors of your site. Are any text or links there solely for search engines rather than visitors?”

      And then it ends with “If you do find hidden text or links on your site, either remove them or, if they are relevant for your site’s visitors, make them easily viewable.”

      I may be interpreting it wrong but this article seems to clearly describe hiding content so that it’s not easily viewable. He literally has a class called “visuallyhidden.”

      As far as I know Google doesn’t parse anything in an element with “display: none;”. However, it does parse content with a “left: -999em;”. When it parses the former it won’t affect your SEO but when it parses the latter it will scan the content of the element and see if you’re trying to game their system.

      I may be wrong but that’s my current understanding.

    • joe
      Permalink to comment#

      Here I found a blog articles (a bit dated) about this concept:

      http://luigimontanez.com/2010/stop-using-text-indent-css-trick/

      http://maileohye.com/html-text-indent-not-messing-up-your-rankings/

      Obviously things may have changed and they don’t seem to offer ways around the problem besides media queries. I still avoid hiding things off-screen in this manner.

    • joe
      Permalink to comment#

      One last response by me.

      It seems that you’re correct for the most part. Sites utilizing this technique will only be marked by Google–not penalized. If they discover further SEO spamming on your site the hidden technique can be used to penalize your site further, however, the technique alone is not enough to damage the SEO of your site.

      Like you mentioned, intent does matter. But without Google releasing their algorithms it seems we never really know what will does what without trial and error.

  20. Joshua
    Permalink to comment#

    Thanks for this post. I’m just about to start a few sites that most likely the users are going to be using screen readers and this has helped a lot…Thanks

  21. Permalink to comment#

    Always good to remind developers that display:none makes content inaccessible to screen readers. It’s often misused, albeit unintentionally.

    Still, there are many cases where display:none is the appropriate way to go. Screen reader users generally expect the page’s content as provided to them to represent the actual page content as displayed on the screen. Also note that not all screen readers are blind.

    Additional content like headings or explicit form labels positioned offscreen where these serve to help screen readers programmatically offer users a better understanding of page structure or relationships are totally fine, should they be superfluous visually. However, in other cases, for example, unselected tab panels, I’d argue that display:none is what’s required.

    Properly implemented tabbed interfaces are familiar to screen reader users who have an expectation of their functionality. In that familiar presentation, only the currently selected tab panel is available to the screen reader, or any user for that matter. This is part of the tabbed interface having a ‘state': when the second tab control is active, only the second tab panel is available. When all tab panel content remains accessible, even if positioned offscreen, not only will a screen reader announce all of it, making a sighted screen reader user wonder what content is being read as it’s not visible on screen, but it will not be as clear to blind screen reader users what tab control is currently active, since all tab panels are available. And if the tab panel content positioned offscreen contains focusable elements, these will remain in the keyboard TAB order, adding additional but effectively invisible TAB stops, but when they gain focus, this focus will not be visible on screen, thereby affecting and possibly confusing all keyboard users, visually impaired or not.

    Here’s one good article addressing this general issue: http://simplyaccessible.com/article/better-for-accessibility/

    Cheers

    • Derek Featherstone’s article you linked to, Jason, was the exact reason I wanted to comment. Glad to see you’ve beat me to it! :-) It’s a good intro to why sometimes display:none is appropriate and sometimes not.

  22. If you think about using z-index, don’t forget the maximum value of z-index!

  23. MMM
    Permalink to comment#

    Question: Why do you want to make hidden content available to a screen reader in the first place? If you “fade out” some content after a user action, why should it be available to the screen reader since it can’t be seen by a regular user? We’ve made the content redundant, why is it still needed? It looks to me like a over-thought solution for a non-existent problem.

  24. OK well that is pretty important !

  25. Permalink to comment#

    I use it with multilevel menus pure css with css3 transitions.

  26. Permalink to comment#

    The WAI-ARIA spec specifies a hidden state which should be used and has a few very important points about visibility in accesssibility:

    Note: Authors are advised to use extreme caution and consider a wide range of disabilities when hiding visibly rendered content from assistive technologies. For example, a sighted, dexterity-impaired individual may use voice-controlled assistive technologies to access a visual interface. If an author hides visible link text “Go to checkout” and exposes similar, yet non-identical link text “Check out now” to the accessibility API, the user may be unable to access the interface they perceive using voice control. Similar problems may also arise for screen reader users. For example, a sighted telephone support technician may attempt to have the blind screen reader user click the “Go to checkout” link, which they may be unable to find using a type-ahead item search (“Go to…”).

  27. Permalink to comment#

    Chris —

    Excellent points and extremely relevant. So often unless our clients require it or a target demographic need it to use a site, we forget these important things.

    For those who are looking for a good Screen Reading emulator, Firefox has a great add-on called ‘Fangs’ (based on JAWS) here: http://bit.ly/io5aks . We’ve been using it to see what the reader will spit out and it’s been really helpful.

    Thanks for the post!

  28. Permalink to comment#

    I read comments about designing for people who disable Javascript all the time. Does anyone really disable Javascript on a modern computer using a modern browser?

    • Ade
      Permalink to comment#

      Apart from the many users of NoScript, I can only comment for myself. If I’m using Firefox, yes, JS is kept disabled except for a whitelist. Otherwise, I use Dillo on Linux. In both cases, the primary reason is usability/accessibility issues.

  29. Permalink to comment#

    very informative post. i’m just learning about accessibility and how to design and code websites accordingly. thanks for the post!

  30. Julian Cizmic
    Permalink to comment#

    Wait, can’t you just use

    visibility:  hidden;

    ???

    • Ade
      Permalink to comment#

      To ATs, that behaves the same as display:none, because of their use of an accessibility layer. So would be fine to use when display:none is also appropriate, if you want the effect if vis:hidden, but if you need something to remain accessible, it won’t be.

  31. Thanks for the info, will be taking it for a test run and playing with it.

    It is sad however how the disability guidelines have been sidelined over the years and eye opening to see the consequences of it all.

    Thanks for the article.

  32. Makes sense, whilst we were designing out new recruitment system we tried to cater for screen readers. I’ve never used so many title tags in my life!

  33. Good read, I never put much thought into this. I’ll use it in this manner forward for additional accessibility.

    Cheers,
    Chris

  34. working at an agency, most of our clients could care less about accessibility, as long as it works on tablets and phones, and often not even that. it’s all based on how little they can pay and still get what they want from us. this kinda thing would never be paid for, but it’s a good idea. still, i don’t see a point in showing screen readers something that you want to hide.

    • Ade
      Permalink to comment#

      You don’t? Have a read through the other comments: the point of creating content for ATs (not just for screen-readers) has been covered.

      And if clients were not prepared to pay for a respectable basic standard of accessibility, I wouldn’t have a business.

  35. What a pain in the behind this trick is, but I have to say The Filament Group wrote a great article on hidden elements that included discussions on using ARIA attributes. There is also a good reference to some of the pros and cons to the 4 principles outlined by the WCAG that must be met to ensure content is accessible.

    http://filamentgroup.com/lab/expand_and_collapse_content_accessibly_with_progressive_enhancement_jquery

  36. Permalink to comment#

    I’ve started using this technique just a few weeks ago… it finally hit me!

    I have thumbnails of posts on the home page of our blog and used to display only the thumb… but now have it set to display the thumb, title, and excerpt and have those hidden off the page so that you have that content within the code.

  37. Are you saying that if content is hidden on initial page load with display:none;, that it will never be able to be read by screen readers, no matter what changes happen to the DOM after page load?

    • Mark
      Permalink to comment#

      It’s not really about the DOM, since few ATs (and no screen-readers, IIRC) access it directly: it’s about a browser’s accessibility layer and disp:none is supposed to keep elements out of the layer.

    • Mark
      Permalink to comment#

      And I forgot to add that the element should go into the layer if disp:none is removed, though it’s often the case that the change won’t be picked up by the AT unless ARIA is used (and it’s ARIA-aware).

  38. Permalink to comment#

    Good information Chris. I’ll be sure to make a note of that if I’m risking losing quality content, but I’d argue that rather than us nitpicking the code and increasing our workload, that we simply produce hordes of great content (enough so a few display:none’s don’t cloud anything) and let Google sort out the good sites from the bad ones.

    What’s up with my portfolio tut? :)

  39. John
    Permalink to comment#

    Thank you for the great article Chris. In my current position, I have to make sure that our site is accessible and 508 compliant. We do not use display:none; but rather using the technique you have described to hide the content off the screen.

    In addition to making content accessible, the other half of the equation is that we need to make sure the site is usable. Meaning, the reason you might hide content is because you want to add and hide a link that skips the navigation and anchors to the main content of the page.

    Why? Imagine using a screen reader and having to tab through a header with a few links, and then the navigation with many links, and maybe a small set of social media links, that’s a lot of content the user may not need. But if they land on the page, and the first link they can hit says “Link to skip to main content”, it lets that user skip “useless” content and go to what they want, the main content on that page.

    Those not using AT take for granted we can just look and click to get what we want.

    And yup, Fangs for Firefox is great way to simulate what a screen reader outputs, and if you are inclined, take a look at FireEyes for Firefox, it’s free (not a spokesman!).

  40. woh ! very important thing . i will keep this in my mind . Thanks for share :)

  41. Frank van Gemeren
    Permalink to comment#

    Using negative offsets still creates a huge box that needs to be rendered off-screen.

    A faster way is:

    .hide-text {
    text-indent: 100%;
    white-space: nowrap;
    overflow: hidden;
    }

    Via http://www.zeldman.com/2012/03/01/replacing-the-9999px-hack-new-image-replacement/

  42. Permalink to comment#

    An addition about the naming thing: “.visuallyhidden” is way too long for me. That’s why in my projects I renamed the “.hidden” to “.away” (because it’s physically not there anymore) and “.visuallyhidden” to “.hidden” (because it’s… well… hidden outside of the viewport).

  43. I used display:none so many times. I wonder if there’s a way to use server-side scripts (php) for that.
    My concern is not just to hide the element but also not load it if it’s hidden. For example, on a mobile device stylesheet, I hide certain elements that show in the desktop view; and at the same time I don’t want them to load on the mobile version because it may slow down the page a little. Any ideas?

  44. Gregorio Ramirez
    Permalink to comment#

    Screen readers are pretty much up there with ie6.

    • Ade
      Permalink to comment#

      That is one of the most crass, ill-informed, and wholly inaccurate comments here.

    • Gregorio Ramirez
      Permalink to comment#

      It’s quite informed, but not what you want to hear. I’m pretty sure the share for sr is so low it’s not even worth going into so much trouble to satisfy a few. If you digress I’d like to see some real stats that prove otherwise.

    • Ade
      Permalink to comment#

      If you have used any AT, you know that most of them, particularly screen-readers, are more sophisticated than any browser, most of all IE6.

      It takes very little effort to build AT-friendly websites. Just some knowledge, empathy, and thought. Things that all developers should possess. There is not much that can excuse not knowing basics like this particular topic, which has been written about so many times for years now.

      If people want user data, they can get it from any national body that represents disabled people. But to try to reduce disabled people like me to mere statistics is unproductive, uncaring, and quite offensive. And such data is largely irrelevant because we all can and should build websites that are usable by everyone who can use the web. If someone can use website A, they should also be able to use the similar website B, because it can be build to the same standard. Whether doing that accommodates an extra 0.1%, 1%, or 10% is orthogonal in the context of inclusion and must never be used as an excuse for not ensuring a reasonable standard of accessibility. Or doing one’s job properly, to put it another way. Developers should not complain about doing some very simple things that make a vital difference to some of us.

  45. great points, and tutorial. Another thing people don’t think about is that display:none and visibility:hidden get your code to come up in malware scanners, the same as gzip, eval, and base64 decode statements. Good to hear there’s another (or better) way to do the hidden code thing.

    Thx for the blog post!

  46. tyrone
    Permalink to comment#

    What is the different effect of using either in terms of being penalised for ‘ghosting’ content?

  47. It is a very much informative right to the point article with some good resources. Thanks a lot for sharing.

  48. Note that display:none is not always bad regarding a11y.
    For example, it can be used with complex menus a la drop-down or fly-out.
    That’s because using display:none (vs. position:absolute with a negative offset) removes elements from the tabbing flow which helps users navigate through very long menus… and the page.

  49. Yan
    Permalink to comment#

    display:none; is still useful for elements that are not necessairly readable…

  50. Papa Carlo
    Permalink to comment#

    What’s wrong with visibility:hidden ?

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".