In HTML, how can I have text that is only accessible for screen readers (i.e. for blind people)?
Asked Answered
U

6

76

I have a website that has colored divs with numbers, e.g. a red block with the number 2 inside of it. The color is important to understanding. A blind user emailed me asking if I could make it say "2 red" for his screen reader.

I tried adding this as an alt="2 red" but he said that didn't do anything. He thinks it might only read alt tags for images.

Is there a good way to do this for divs?

Unfriended answered 25/9, 2014 at 6:33 Comment(0)
E
107

As far as alt text, you are correct, that only works for images.. But you can use aria-label in place of the alt attribute for non-image elements like so:

Solutions that work

ARIA Labels ★ ★ ★ ★ ★ ★

aria-label (not to be confused with aria-labelledby, a related tag that instead pulls the accessible name from the text of another element) is used to add off-screen descriptive content to an element much in the way an alt= attribute adds off-screen descriptive content to images to be used when the images are not displayable.

The difference is, aria-label can be used on non-image elements.

<div aria-label="test A"><p aria-hidden="true">test B</p></div>
<!--
     result (screenreaders):  test A
     result (regular):        test B
-->

The addition of the aria-hidden attribute hides the inner text.

Position + Clip + Collapse ★ ★ ★ ★

.screenreader {
    position: absolute !important; /* Outside the DOM flow */
    height: 1px; width: 1px; /* Nearly collapsed */
    overflow: hidden;
    clip: rect(1px 1px 1px 1px); /* IE 7+ only support clip without commas */
    clip: rect(1px, 1px, 1px, 1px); /* All other browsers */
}

The clip is used to hide the 1px x 1px element completely, otherwise it will still be visible on the screen.

Position ★ ★ ★

.screenreader {
    position: absolute;
    left:-9999px;
}

<div>Wed<span class="screenreader">nesday</span>, Sept<span class="screenreader">ember</span> 24, 2014</div>

Indent ★

.screenreader {
    text-indent: -5000px;
}

The actual indent value is not important as long as it's outside of the range of your pages layout. The example will move the content to the left 5,000 pixels.

This solution only works for full blocks of text. It won't work well on anchors or forms, or right-to-left languages, or specific inline-text intermixed with other text.

Will not work

visibility: hidden; and/or display:none;

These styles will hide text from all users. The text is removed from the visual flow of the page and is ignored by screen readers. Do not use this CSS if you want the content to be read by a screen reader. But DO use it for content you don't want read by screen readers.

width:0px;height:0px

As above, because an element with no height or width is removed from the flow of the page, most screen readers will ignore this content. HTML width and height may give the same result. Do not size content to 0 pixels if you want the content to be read by a screen reader.

Further:

Eudocia answered 25/9, 2014 at 6:41 Comment(9)
The person actually told me that aria-label doesn't work with his reader even though the spec says it should...Unfriended
aria-label does not work with Jaws when I attach the attribute to a standard div, nor does aria-labeledby, has anyone figured out why? I'm using this with FF and IEWapentake
aria-label is only allowed on something with an explicit role, so I don't understand how the "best" example works either.Lenis
Anyone able to comment on how hiding screen reader text affects SEO? AFAIK GoogleBot considers text hiding to be manipulative and may penalize your SEO ranking for it.Woodland
FYI: aria-hidden="true" solution did not work for me. In that I could still see the content on the non-screenreader page.Comras
FWIW, Chrome's Lighthouse Accessibility Audit (based on WAVE) will complain at you if you use aria-label on an element that doesn't have an "interactive" role, which is perhaps a point against using aria-label on <div/>s, <span/>s, etc.Walkover
clip is now deprecated. Instead clip-path: inset(50% 50% 50% 50%); should be used.Nippers
Microsoft Edge "Read Aloud" ignores aria-label and 1px elements (width or height). Only option 3 works on it.Harney
Think you can do this just by adding aria label to the p, skip the rest.Amandie
V
6

EDIT 2020: currently display:none or visibility:hidden seems to generally cause that the content is not visible visually and for screenreaders (just tested in Firefox and Chrome with NVDA), so the statement below is invalid. moving content outside of the screen currently seems to be the only way to provide content only for screenreader users, also see this table: http://stevefaulkner.github.io/HTML5accessibility/tests/hidden-2016.html


Unless differently stated in the accepted answer at least Chromevox1 and NVDA2 do also read elements with style display:none or visibility: hidden CSS attributes if aria-hidden=false is set. However currently only in Chrome (65), not in Firefox or Edge (according to my tests).

So (currently unfortunately only in Chrome) its also possible to do something like this:

<h1 aria-hidden="false" style="display: none;">Heading only for Screen Readers</h1>
<h1 aria-hidden="false" style="visibility: hidden;">Second Heading only for Screen Readers</h1>
<h1 aria-hidden="true">Heading only for Screen</h1>

where Chromevox and NVDA read the first and second heading. Also see this: https://jsfiddle.net/4y3g6zr8/6/

If all browsers would agree on this behaviour it would be a much cleaner solution than all CSS tricks proposed in the other solutions.

1Chromevox https://chrome.google.com/webstore/detail/chromevox/kgejglhpjiefppelpmljglcjbhoiplfn 2NVDA https://www.nvaccess.org/

Ventricular answered 20/4, 2018 at 11:22 Comment(1)
Thanks, exactly what I was looking for. It would be good to have a tabular overview of what takes precedence in which browser/screenreader combination and also what should take precedence from an standards perspective.Kopple
C
4

You can put a visually hidden element inside:

<div>
    <span class="visually_hidden">2 red</span>
</div>

To "visually hide", you can borrow how HTML5 boilerplate does it:

.visually_hidden {
  border: 0;
  clip: rect(0 0 0 0);
  height: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
  width: 1px;
}
Capablanca answered 25/9, 2014 at 6:41 Comment(0)
O
1

Regarding the question in the title: No, there is no way (in HTML or otherwise) to have text that is only accessible for screen readers. Whatever you might do, like using an img element with a nonempty alt attribute and a missing or dysfunct src attribute` or using CSS to hide something visually, will be available to any software that cares to read it (and may be inaccessible to screen readers for one reason or another).

On the other hand, if you actually use e.g.

<div class=foo>2 <img alt=red></div>

then most screen readers will read it as “two red”, but so will well-behaving normal browsers, so the effect is not limited to screen readers.

What you should do for accessibility is a different issue and depends on the context and on the purpose of using red color. Note that even when the browser displays a box as red the user might not see it as a red, due to color-blindness; in particular if it is relevant to distinguish between red and green, many people will fail to do so.

There might be a simple solution in a specific case, or it might be a tricky problem with no good solution. For general notes and various techniques, see the document How to Meet WCAG 2.0: Use of color.

Obi answered 25/9, 2014 at 8:3 Comment(1)
Hi, is this still the workaround solution in 2016? I also am trying to find out if there is a way to address having a string read only by the screenreader that is attached to the divWapentake
I
0
<div role="img" aria-label="red 2">
   <span aria-hidden="true">2</span>
</div>

This will work. role="img" is necessary if you want the screen reader to read anything on mouse-hover.

Tested in ndva.

Incurious answered 10/2, 2022 at 9:52 Comment(0)
C
-2

How about making the font color totally transparent? I don't have a screen reader to test if this type of text is readable by screen readers.

.hovereffect a.info {
    color: #9c27b000 !important;
}
Colvin answered 14/6, 2019 at 15:12 Comment(2)
Transparent text can still be detected by the search-function in the browser and can also be selected by CTRL+A and thereby invisible to all users.Colson
This is a rather simple and clever solution. You can also reduce the font-size to the smallest size possible, and the screen-reader will find it, and it will be practically invisible for sighted users. I've tested it, and it works acceptably. I would say that using !important is not necessary. I applied this solution to a h2, between a h1 and a h3, just using "color camouflage" and "size atomization", and it worked like a charm.Otter

© 2022 - 2024 — McMap. All rights reserved.