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

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.