Summary

The standard method for hiding text visually to retain a clean design but provide context for screen reader users is to use the CSS clip technique. Due to browser bugs with the clip property, other declarations are used to make this technique work correctly across different browsers.

Two of the properties used in the additional declarations for the clip technique are position and overflow. Unfortunately, due to a bug with Firefox, when these two properties are used together in a rule applied to the label element (regardless of property value), they cause the label text to not be exposed as the accessible name for the corresponding form control. The position and overflow properties are also used in other techniques for hiding text visually, but this bug means the accessible name will not be available for screen reader users when applied to a label element.

Author: Gez Lemon

Providing context

There are times when things make sense visually, but context would be useful for screen reader users. For example, "read more" links might make sense visually, but when tabbing through content with a screen reader, the user needs to investigate the surrounding content to get the context for each "read more" link; whereas, "read more about The Beatles" provides the context within the link phrase. To avoid disrupting a clean design, accessibility aware developers provide the context so that it's available for screen readers, but hidden visually. The following markup example provides the context for a "read more" link in a span element.

A "read more" link with context
<a href="beatles.php">
  read more
  <span class="context"> about The Beatles</span>
</a>

The span element in the above example can then be targeted with CSS so that it isn't visually displayed, but announced to screen reader users for context.

Techniques for hiding text visually

There have been several techniques used to hide content so that it is still available for screen reader users, but the clip technique is generally agreed to be the best solution as it satisfies the requirements of hiding the text while ensuring the text is still readable with a screen reader, and works with left-to-right and right-to-left languages. If browser support for CSS was implemented correctly across browsers, the following CSS rule would be all that's required to hide content visually.

Hiding content using the clip property
.context {
  position: absolute !important;
  clip: rect(1px, 1px, 1px, 1px);
}

Unfortunately, other CSS properties are needed to overcome rendering bugs in some browsers. For example, Safari, Chrome, and Opera sometimes introduce scrollbars depending on the size of the element and its position on the page. IE6 and IE7 do not support the correct syntax for the clip property. The following is an example of the CSS rule with other declarations to ensure it works correctly across browsers.

The clip technique with additional declarations for browser support
.context {
  position: absolute !important;
  clip: rect(1px 1px 1px 1px); /* for IE6 and IE7 */
  clip: rect(1px, 1px, 1px, 1px);
  padding: 0 !important;
  border: 0 !important;
  height: 1px !important;
  width: 1px !important;
  overflow: inherit;
}

Firefox label bug

When the CSS properties position and overflow are used together in a rule that is applied to the label element with any valid property value, the label text isn't exposed as the accessible name for the corresponding form control in Firefox; even if the values are the default values for the property (position: static and overflow: visible). This means that when a screen reader user navigates to the corresponding form control for the label, they do not hear the accessible name that should be provided by the label; instead, they simply hear the role of the form control. For example, without an accessible name a screen reader might announce an edit box as, "Edit, type in text", rather than the label text to provide the purpose for the edit box. The label can be navigated to virtually in NVDA and JAWS, but the label isn't exposed as the accessible name for the form control as it should be.

My colleague, Hans Hillen, filed this is as bug with Firefox last year, but the bug hasn't been assigned to anyone yet. As the position and overflow properties are used together in several techniques for providing invisible context for accessibility purposes, it is important developers are aware of this bug and that it is fixed soon in Firefox.

Workarounds

We generally recommend the title attribute or the aria-label attribute if there is no visible label at all (such as checkboxes arranged in grids that make sense visually). We only recommend using the CSS clip technique when the rule is applied to some of the label, rather than the entire label. Until this bug is addressed in Firefox, using the title attribute or aria-label attribute are the recommended techniques for providing a programmatic label for form controls that do not have a visible label.

Providing an accessible name with the title attribute
<input type="checkbox" title="Personal bank account" ⋯>
Providing an accessible name with the aria-label attribute
<input type="checkbox" aria-label="Personal bank account" ⋯>

If the label approach must be used and then visually hidden, apply the CSS rule to a span element within the label element, as the bug is only triggered when the rule is applied to the label element.

Using a span element in a label element
<input type="checkbox" id="pba" ⋯>
<label for="pba"><span class="context">Personal bank account</span></label>

Category: Accessibility.

Comments

  1. [hidden-label-firefox-bug.php#comment1]

    Hey, Gez.

    The code I use for hiding things visually is as follows:

    
    .a11y-hide {
       display: block; /* so height is honoured */
       height: 0;
       padding: 0; /* because box model means padding will make it taller again :-( */
       overflow: hidden; /* so nothing sticks out */
       position: absolute; /* to remove from flow */
    }
    

    That's as much brevity as I've managed without clip and seems to be pretty robust.

    Regarding aria-label: There is a bug that means Firefox+NVDA won't honour it on <button>s. These aren't always strictly form controls, I know. But still *smile*

    Posted by Heydon on

  2. [hidden-label-firefox-bug.php#comment2]

    Hi Heydon,

    Thanks for the comment. As with most techniques, the technique you're using uses the position and overflow properties, so would also be subject to the Firefox label bug. Hopefully, they'll get it fixed soon.

    Posted by Gez on

  3. [hidden-label-firefox-bug.php#comment3]

    What's wrong with the usual method?

    
    label {
      position: absolute;
      left: -999em;
      height: 0;
    }
    

    aria-label only works with newer UAs + newer screen readers. Title may depend on the user having turned them on or explicitly asking for them.

    I've never used overflow: hidden but *specifically* avoided it after the VoiceOver bug.

    Posted by Stomme poes on

  4. [hidden-label-firefox-bug.php#comment4]

    Hi Stomme,

    The problem with the off-left technique is that it causes huge scrollbars in right-to-left languages. For sites that serve different language systems, it requires logic to decide whether to push the content to be hidden left or right. Also, to be bullet-proof, that technique is usually used with width and overflow properties to ensure it doesn't bleed into the viewport. The bug that Hans has reported with Mozilla originally used the off-screen technique using those properties to ensure content doesn't bleed into the viewport (changed in the example to isolate the properties causing the bug), and the Firefox bug is triggered using that technique of hiding content.

    The title attribute for form controls does not depend on a screen reader user's verbosity settings. In the absence of an explicit label, the title attribute is reliably conveyed as the accessible name by browsers, and exposed to assistive technologies using the accessibility API.

    Posted by Gez on

  5. [hidden-label-firefox-bug.php#comment6]

    Hi Dennis,

    Removing the overflow property does correct the bug with Firefox, but then causes issues with unwanted scrollbars being introduced with Safari, Chrome, and Opera in some situations (if the element is large enough to cause a scrollbar without the clip, and positioned near the edge of the viewport). Some of the declarations added to the clip technique for hiding content visually are added to avoid that scenario. If Safari, Chrome, and Opera implemented clip as it's defined in the CSS specification, most of the extra declarations would not be required for the clip technique (apart from dealing with IE6 and IE7). But other techniques for hiding content (one mentioned in a previous comment) also depend on position and overflow being included in the same rule, so it is important this issue is fixed in Firefox.

    Posted by Gez Lemon on

  6. [hidden-label-firefox-bug.php#comment7]

    Awesome, thanks for clarifying, Gez. Let's hope Firefox and other browsers fix these issues. Causing quite a mess (as usual, ha ha).

    Posted by Web Axe on

  7. [hidden-label-firefox-bug.php#comment8]

    Hey Gez, great article! I've seen this bug plenty of times. I also see a bug in iOS where a visually hidden label positioned off screen causes the whole page to shift focus to an empty gray area. I guess it's the VO cursor trying to find something to focus on visually. It's no problem for screen reader users it just looks terrible visually like the page is broken.

    It seems like there's not really a good reason to use visually hidden explicit labels when there are these bugs and just using the title or aria-label is less code and less buggy.

    So is there a good reason to use visually hidden labels?

    Thanks!

    Posted by Paul J. Adam on

  8. [hidden-label-firefox-bug.php#comment9]

    Hi Paul,

    Thank you. At the moment, my advice for visually hiding labels is to use the technique when only a part of the label is to be hidden. If the whole label is to be hidden, then the title or aria-label attributes are safer. But as many developers do use visually hidden labels, I hope this bug is fixed soon.

    Posted by Gez on

  9. [hidden-label-firefox-bug.php#comment11]

    Just to clarify, does Dragon support the title attribute consistently? As their support for aria-label is questionable, should we focus on the title attribute?

    I appreciate the suggestion to use the clip on the span instead of the label. This would make it easier to retro-actively fix sites that are currently using clip on the label.

    Posted by Ted Drake on

  10. [hidden-label-firefox-bug.php#comment12]

    Hi Gez,

    Thanks for the heads-up and for proposing "patches".

    As a side note, I believe you have a typo in the code example for the clip technique. It says:

    position: static !important;

    instead of:

    position: absolute !important;

    Posted by Thierry on

  11. [hidden-label-firefox-bug.php#comment13]

    Hi Ted,

    Good question regarding Dragon. Dragon is an important assistive technology, and I would cater for it as much as I could providing it was also the best solution for other assistive technologies. In the instance of providing an accessible name for a form control when a visible label isn't viable, I would choose title over aria-label, as that is exposed correctly by older browsers (and so can be consumed by any AT). When older browsers are no longer important, I wouldn't allow decisions going forward to be hindered by Dragon (or any other AT), as they also have a responsibility to make sure they support standards and recognise accessible features and expose the correct information to their users.

    Posted by Gez on

  12. [hidden-label-firefox-bug.php#comment15]

    Hey Gez. I didn't know this method, It is quite interesting. I also used to add absolute position as Stomme mentioned but it is definitely not the best solution. Thanks.

    Posted by François on

Add your Comment

Please read the comment guidelines before posting your comment. Email addresses are not displayed.