When and How to Visually Hide Content

Tweet

Visually hiding content on a web page, usually textual content, is at times a viable technique in web design and development. It can be done for several reasons, most importantly, to improve the experience of a screen reader user. Other reasons include improving readability when CSS cannot be rendered, and improving search engine optimization (SEO). For screen reader users, situations where the need arises include:

  • Labeling a form element that has meaning conveyed visually, but not otherwise, such as inputs for search and phone number area code.
  • Providing headings where related content has meaning conveyed visually, but not otherwise, such as a menu.
  • Hiding “skip-to” links—anchor links which jump over large blocks of content on a page. These type of links should be focusable and viewable for sighted keyboard users. The most typical is a “skip to main content” link at the beginning of a web page which often jumps past the web page mast and global navigation.
  • Providing special instructions in special circumstances where interaction may be confusing to users of assistive technology. Use discretion with this, and be careful when doing so; it’s important to not be condescending like the UK Census website.

Note that visually hiding content is a separate concept to content which is completely hidden purposely, a technique which can be designed for all users. An example is a set of tabs and panels where only one panel of content is displayed at a time. Using the CSS display:none and/or visibility:hidden in this case is an adequate and acceptable solution.

Classic Method

For years, a widely implemented and accepted method for hiding content has been used. The WebAIM explains it well in their article CSS in Action: Invisible Content Just for Screen Reader Users. Here is an example of the classic method of coding hidden content, absolutely positioning the element containing the text and moving it off the screen:

.hidden {
    position: absolute;
    left: -9999em;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
    }

<div class="hidden">Hidden content here.</div>

Variations in the CSS have kicked around over the years which include using a negative top position (instead of left); negative text indentation; and a height of 0.

Issues have been discovered with the classic method and its variations such as:

  • may cause the viewport to jump awkwardly when an invisible element receives focus
  • negative text indentation method will not work when direction of language is right-to-left
  • the VoiceOver screen reader (Apple) will not read content within an element that has 0 height
  • hidden headings may be spoken as “text heading” instead of the heading text (reported with Safari with VoiceOver on SnowLeopard)

New Method: Clip

A new method for visually hiding content has recently emerged to solve these issues, known as CSS clipping. It was apparently first pioneered by Jeff Burnz in his AdaptiveThemes article Using CSS clip as an Accessible Method of Hiding Content. The core concept boils down to this snippet below. Essentially, the CSS 2.1 clip property lets you specify the dimensions of an absolutely positioned element using top, right, bottom, and left values, creating a boxed container for the content. By setting all values to 0 pixels, the content becomes invisible.

.hidden {
  position: absolute;
  clip: rect(0px 0px 0px 0px);
}

In theory, this should work perfectly, but we all know browser rendering can vary quite a bit and browsers many times do not adhere properly to the W3C standards. Screen reader applications may also behave differently. Other developers have improved the clip method including Jonathan Snook in Hiding Content for Accessibility and Thierry Koblentz in Clip your hidden content for better accessibility. So after several iterations and a lot of hard work in the community, some great bulletproofing enhancements were made including (see the final code below):

  • Accommodating different syntax in IE6 and IE7; see line with comment.
  • Correcting a bug in Webkit and Opera where clipped content causes overflow when guidelines says it should not; fixed with overflow:hidden.
  • Set height to 1 pixel to ensure VoiceOver reads the content.
  • And as an added precaution, the padding and border attributes are set to 0 in order to prevent any issues related to the edges of the clipped box.

Here's the final code snippet. Notice that the clip values changed from 0 to 1, which accomplishes the same result. Add this class or replace your current class with this one, and you have a much more solid and accessible technique for hiding content!

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

Summary

There are several reasons you may want to hide content on a web page, primarily for screen reader users. The classic CSS method works, but there may be issues under certain edge cases. The clipping method to hide content thus far has proven to be an improved technique. Some extra code is still required to accommodate all browsers and screen readers, but overall is a more solid solution.

Further reading:

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.facebook.com/profile.php?id=1483392824 Chad Royer

    Is there a reason a simple .hidden{display:none;} wouldn’t work?

    • Louis Simoneau

      Most screen readers won’t read text that has display:none

      • http://www.facebook.com/profile.php?id=1483392824 Chad Royer

        Thanks, Louis… I did not know that. I always thought screen readers ignored all CSS.

        • http://twitter.com/dennisl Dennis Lembrée

          Yep, screen readers will ignore content with display:none. Also note that in a recent survey by WebAIM.org, approximately 98% of screen reader users had JavaScript enabled (roughly the same as sighted users).

  • http://twitter.com/artopaavola Arto Paavola

    I prefer a method where tabbing to a “hidden” link (for example to a Skip to content link) with keyboard makes the link visible to the user. This is very helpful for people who need (or want) to use the keyboard for moving around the page. How is this done with the clip method?

    • http://twitter.com/dennisl Dennis Lembrée

      Great point, Arto. There is an example in the Drupal 7 article under “Further reading”.

  • Kjohnson

    I am confused on the topic of hiding text and SEO. This article says it can improve SEO. From what I understand, Google frowns on hiding text, as it is a technique used by spammers; “frowns on” to the extent they will ding you in the search rankings. Can anyone clarify?

    • http://twitter.com/dennisl Dennis Lembrée

      Sorry for any confusion. Can’t clarify for sure, but I can say this:
      -Google changes its algorithms often.
      -I doubt Google penalizes for minimal amount of text; pretty sure they’re smart enough to detect when there’s keyword stuffing or not.
      -Google is the biggest, but not the only search engine.

    • Louis Simoneau

      From everything I’ve read, my understanding is that Google is smart enough to tell the difference between UI text hidden to be replaced with visual elements and keyword stuffing. Small amounts of text that aren’t stuffed full of keywords are fine.

  • Avenewz

    Not sure how relevant it’s here but content can be hidden on demand with jQuery or similar. Done exactly that for a local GP consortium portal where certain content need hiding/showing. jQuery also provides a nice show/hide transition.

  • http://webaim.org/ Jared Smith

    There’s nothing broken with positioning off-screen left. CSS clip causes the same viewport jumping that off-screen content does. The browser will always try to focus the element whether off-screen or clipped. It’s rare, anyway, that one would want to hide a functional element such as a link.

    Despite rumors, off-screen left works fine with RTL content. It also causes no known VoiceOver issues (those noted above refer to other techniques).

    I can’t help but wonder if the CSS clip approach is a fix for a problem that does not exist. I’ve yet to see anyone documented case where off-screen left content is ‘broken’ or in any way improved by CSS clip.

    And for SEO concerns, Google uses off-screen left for the first link on google.com, as do many, many other major web sites. Google has assured us that off-screen text alone does not impact rankings.

    • http://twitter.com/dennisl Dennis Lembrée

      Thanks for your input, Jared. I worked with Everett Zufelt recently in fixing a bug in AccessibleTwitter.com directly involving the method of hiding text for a heading. In the classic method, the screen reader spoke “text heading” instead of the actual content of the heading. When changed to the clip method, it functioned properly. I was told the testing was with Safari with VoiceOver on SnowLeopard.

      • Lebisol

        Again… a fix for one instance is nothing more than a hack.
        Jared is right…let it go people.

  • Info

    I too had heard that Google frowned up on the use of hidden text for SEO. be good to get a straight answer on this.

    • jules

      I once put some markup in a page like this;

      [span class="hide"]blah blah blah[/span]

      The page disappeared from Google’s results entirely. Other pages from the same site were fine. I removed the offending code, and sure enough the page was listed again.

      Not proof of anything, but interesting.

  • Manu De Mey

    This is a very useful way of hiding content for chinese web developers.
    The rest of us will just keep on using the negative text indentation:

    text-indent: -9999px;

  • McBenny

    This method only works if you want to add text that shall not be visible.
    My greatest usage of hiding text is when a “text element” (a heading mostly) is finally treated with an image (to use an exotic font for example). Thus the block containing the image must be visible and in the viewport. Any clipping would hide the image. No matter how the image is used (as an img tag or as a background of the block.
    In this sort of situation, you can only use a text-indent method, can’t you ? Or you rely on adding an extra markup that you’ll clip ?

    • http://twitter.com/artopaavola Arto Paavola

      What about users who have images disabled in their browser? If you hide the heading text with text-indent they don’t see anything at all. I think in this kind of a situation it would be best to mark the text inside the header element with a span and use z-index to place the image on top of the text.

      • Lets get this ball rolling!

        If there were such a thing as foreground-image: url()…
        you could have your basic text in a div and an image overlayed on top of it, thus hiding the text. If images are turned off then the basic text would be visible and selectable.

  • Fuckyoudisqus

    As comments are disabled on the Sitepoint abstract, I’ll have to write it here : stop putting those excerpts on the frontpage of sitepoint please. Having to navigate through multiple sites to be able to read one article which only the title prove to be good is getting old fast.

    And while I’m at it : Disqus for comments ? I’m also tired of javascripts used to follow people as they browse around multiple websites.

    • Asdf

      Have you ever replied to some random blog with a lengthy, well written comment then a month later when you’re trying to write content for your own site you realize you could just expand on that comment? Then you spend hours searching for it but can’t find it! While I’m not a fan of disqus they do provide a very useful service.

      It would be better if all blogging platforms by default posted a copy of my comment here back over to the blog on my site so that I’d always have a history of it. They already do pingbacks and such, I don’t see why they couldn’t do this too.

    • http://klepas.org Simon Pascal Klein

      Hiya,

      So a quick rundown: the plan is to move design things from SitePoint slowly over to Design Festival as this has been designated their new home, and we will link things over at SP via exerpts — and I believe other fields will be joining (see the new http://rubysource.com/). I understand your concern. If you don’t like seeing content you’re not interested in (e.g. design content) you can avoid it entirely shortly by just subscribing to feeds from a microsite you’re interested in (or just scrolling past things on SP homepage).

      As for Disqus: it’s not as neat and quick as the inbuilt WordPress commenting system for leaving a quick comment, but it has extra features that we think are worthwhile. If you’re worried about tracking, JavaScript itself doesn’t track you — it’d have to generate cookies or something more nefarious — which I would rather safely say Disqus doesn’t do. :)

      Also, you can post anonymously as you have. (:

      —Pascal.

  • Lets get this ball rolling!

    The classic method and the new method have one horrible thing in common.

    They’re both desperate hacks!

    It should by obvious by now that the W3C, search engine, and screen reader developers need to collaborate and create an OFFICIAL METHOD that addresses these NEEDS.

    All this text indentation, clipping, and off screen positioning are NOT A PROPER SOLUTION.

    off the top of my head:

    #content div.main h1 {
    background: url()…..etc;
    content-visibility: none;
    content-audibility: audible;
    }

    By the way, what are the drawbacks to hiding text using color:transparent?

  • brothercake

    Jared Smith’s experience concurs with my own — the issues you’ve cited either do not exist, or happen equally with the clip or overflow method of hiding text.

    Your case in which VoiceOver gets it wrong, is a bug in VoiceOver; and even if weren’t, a single extreme-minority use-case like that is not enough to dismiss an entire technique, especially a proven technique being replaced by an unproven one.

  • http://profiles.google.com/axel.miller98 Alex Miller

    Isn’t this considered “Black Hat SEO”?

  • https://profiles.google.com/115029199272195697645 ServerStorm

    Nice method, I will start using this and see what negative (if any) feedback is provide.

  • mmj

    What about just positioning as absolute and setting opacity to zero?

    Opacity has good cross browser support if you include Microsoft’s both “filter” property and other browsers’ “opacity” property.

  • http://twitter.com/bloodofeve Claire Kay

    @17903b4c761ade70fdcdc4a119d5fb24:disqus This quite an interesting use of CSS something I will try in the future, I have been using this for a number of years:

    #header {

    position: relative;

    margin: 0 auto 0 auto;

    padding: 0;

    width: 1000px;

    height: 145px;

    overflow: hidden;

    }

    #header span {

    display: block;

    position: absolute;

    left:0;

    top: 0;

    z-index: 1;

    width: 1000px;

    height: 145px;

    margin: 0 auto 0 auto;

    padding:0;

    background: url(../images/header.jpg) top left no-repeat;

    }

    Having a number of testers who use Braille readers and alternative browsers, this seamed a perfect method to include text behind an image, especially if it is used as a background image on a site. I occasionally use this method if an image is used which contains written text, so as soon as you turn off styling the text renders correctly.