64

Screenreaders will read whatever string is set to the "alt" attribute. The use of this attribute is specifically for image tags.

If I have a div like so:

<div id=myCoolDiv tabindex="0"> 2 <div>

Is there a way to have a screen reader pickup an attribute to read a string the same way an alt tag is used?

So for the div listed below, the screen reader will say ie: "shopping cart items 2"?

I tried using aria-label but the screenreader won't pick it up:

<div id=myCoolDiv tabindex="0" aria-label="shopping cart items"> 2 <div>
Kode_12
  • 4,506
  • 11
  • 47
  • 97
  • 12
    what about title ? – singe batteur Jul 14 '16 at 17:02
  • 1
    @singebatteur: Are you sure the `title` attribute is read by screen readers? The [HTML5 spec](https://www.w3.org/TR/html5/dom.html#the-title-attribute) explicitly discourages its use for accessibility. – rvighne Jul 14 '16 at 17:22
  • I encourage you to look at one of the [off-screen techniques](http://webaim.org/techniques/css/invisiblecontent/) specifically designed to provide additional content to screen reader users while hiding it from sighted users. Also, please avoid putting `tabindex` on anything that isn't a real control. – aardrian Jul 15 '16 at 13:48
  • @Kode_12 do you use Bootstrap? You can use `sr-only` class for your purpose. –  Jul 17 '16 at 18:41
  • 1
    Screen reader does not read your `aria-label`, because `DIV` have no default ARIA `role`. You must set `role` to have the `aria-*` attributes activates. – Radek Pech Jul 18 '16 at 13:34
  • just use this link`https://stackoverflow.com/a/62000730/12780274` ,very very short answer – henrry Feb 04 '23 at 15:06

10 Answers10

35

You can just put a title tag in the div which will do the same as an alt tag like so:

<div title="I AM HELLO WORLD">HELLO WORLD</div>

"I AM HELLO WORLD" will be printed once you move your cursor around it on a browser

fedorqui
  • 275,237
  • 103
  • 548
  • 598
Serge Gavrilov
  • 351
  • 3
  • 3
25

There are two ways (which can be combined) to have screen reader to read alternative text:

  1. Anything with ARIA role img can (MUST) have alt attribute. See WAI-ARIA img role.

     <div role="img" alt="heart">
     ♥︎
     </div>
    

UPDATE: In 2017 the WAI-ARIA document was changed and the following text does not apply anymore. See comments below.

However this should be used only in case the element really represent an image (e.g. the heart unicode character).
  1. If an element contain actual text, that just need different reading, you should set ARIA role to text and add aria-label with whatever you want to be read by the screen reader. See WAI-ARIA text role.

     <div role="text" aria-label="Rating: 60%">
     Rating: ★★★☆☆︎
     </div>
    

Do not mismatch it with aria-labeledby which should contain ID of an related element.

  1. You can combine the previous two cases into one using two ARIA roles and adding both alt and aria-label:

     <div role="img text" alt="heart" aria-label="heart">
     ♥︎
     </div>
    

When more ARIA roles are defined, browser should use the first one that is supported and process the element with that role.


One last important thing is that you must set page type to HTML5 (which support ARIA by design).

<!DOCTYPE html>

Using HTML4 or XHTML requires special DTD to enable ARIA support.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+ARIA 1.0//EN"
   "http://www.w3.org/WAI/ARIA/schemata/xhtml-aria-1.dtd">
Radek Pech
  • 3,032
  • 1
  • 24
  • 29
  • ARIA role values are never a space delimited list. The reason why the first item on the list is used is because the rest is invalid. An element may only be assigned one role each, no exceptions, AFAIK. – zer00ne Jul 20 '16 at 17:57
  • @zer00ne "The role attribute takes as its value one or more whitespace separated TERMorCURIEorAbsIRIs, which is defined in [RDFa Core 1.1](http://www.w3.org/TR/2012/REC-rdfa-core-20120607/)." See [WAI-ARIA Role Attribute 1.0](https://www.w3.org/TR/role-attribute/) – Radek Pech Jul 21 '16 at 07:56
  • I concur, sir. I have no idea what the first reference is, but the second one I understand. – zer00ne Jul 21 '16 at 18:20
  • In testing, role="text" worked great with NVDA on Chrome. Didn't work with NVDA on Firefox. – cjaube Nov 06 '17 at 21:42
  • @RadekPech In the link for WAI-ARIA roles, there is no text role. The w3c html validator says that 'text' is a bad value for the role attribute. The validator also complains on using the alt attribute on a div tag. https://adrianroselli.com/2016/12/accessible-emoji-tweaked.html talks about using role="img" and aria-label="some description" combined. – Borje Oct 26 '21 at 11:46
  • @Borje You are right. This post was created in July 2016 and it seems that in 2017 they changed the recommendation and removed the `text` role (since the link https://www.w3.org/TR/wai-aria-1.1/#text does not open anything specific now and instead loads document from December 2017). Now it seems `area-label` is supported only on form elements such as `textbox` (and will be probably handled a bit differently). In any case you can use the role `img` with `alt` attribute (especially if you want it for emoji). – Radek Pech Oct 27 '21 at 10:04
10

Try role="listitem" or role="group" and aria-labelledby="shopping cart items". See Example 1. The 2 is text content which should be read by screen reader already with the attribute read as context to the content. Refer to this section.

UPDATE 2

Add aria-readonly=true role=textbox if you use an input. If there are doubts whether to use aria-label or aria-labelledby, read this article. In the documentation for JAWS and testing it myself supports the fact that aria-label is ignored. Furthermore, semantics are very important when accessibility is your concern. Using a div when you could use an input is not semantically sound and like I said before, JAWS would accept a form element more readily than a div. I assume that this "shopping cart" is a form or part of a form, and if you don't like it's borders, input {border: 0 none transparent} or use <output>* which would be A+ as far as semantics are concerned.

Sorry, @RadekPech reminded me; I forgot to add that using aria-labelledby needs visible text and that the text needs an id which is also listed as the value(s) of aria-labelledby. If you don't want text because of aesthetics, use color: transparent, line-height: 0, or color:<same as background>. That should satisfy visibility as far as the DOM is concerned* and still be invisible to the naked eye. Keep in mind these measures are because JAWS ignores aria-label.

*untested

EXAMPLE 3

<span id="shopping">Shopping</span>&nbsp;
<span id="cart">Cart</span>&nbsp;
<span id="items">Items</span>&nbsp;
<input id='cart' tabindex="0" aria-readonly=true readonly role="textbox" aria-labelledby="shopping cart items" value='2'>


UPDATE 1

For JAWS, you probably have to configure it a little:

  1. Click the Utilities menu item.
  2. Then Settings Center.
  3. Speech and Sounds Schemes
  4. Modiy Scheme...
  5. HTML Tab

In this particular dialog box, you can add specific attributes and what is said when an element is tabbed to. JAWS will respond to form elements easier because they can trigger the focus event. You'll have an easier time doing Example 2 instead:

EXAMPLE 1

<div id=myCoolDiv tabindex="0" role="listitem" aria-labelledby="shopping cart items"> 2 <div>

EXAMPLE 2

<input id='semantic' tabindex="0" role="listitem" aria-labelledby="shopping cart items" value='2' readonly>
zer00ne
  • 41,936
  • 6
  • 41
  • 68
  • What browser are using with JAWS? I've added an update concerning JAWS. – zer00ne Jul 15 '16 at 00:15
  • Internet explorer 11 – Kode_12 Jul 15 '16 at 00:16
  • Attribute `aria-labeledby` is reference to related label element. For actual label is attribute `aria-label`. – Radek Pech Jul 18 '16 at 13:31
  • Note that users will not change their JAWS configuration to read your content. I know this from experience. – aardrian Jul 19 '16 at 21:34
  • @aardrian so you speak for everyone visibly impaired? OP requested that JAWS is name of the game and is using a div. My experience are clients with special needs are assisted in operation of equipment provided which is prepared for proper use. – zer00ne Jul 20 '16 at 17:43
  • Of course I do not, but suggesting that a JAWS user will reconfigure software to use a web site is not borne out by experience with JAWS users (like asking a user to reconfigure their own browser to shop for shoes), even if assisted as you suggest. However, I have done testing with users who install and configure the software on their own. Also, OP does not specify JAWS in the question, only that your option does not work in JAWS. – aardrian Jul 20 '16 at 18:25
  • >this unfortunately, is not read by the screenreader (JAWS)< is a request and requirement, so there's that. – zer00ne Jul 20 '16 at 18:29
  • OP stated "a screen reader" in the question (and the tag), which includes JAWS of course (and hopefully Narrator, TalkBack, NVDA, Orca, and VoiceOver). OP only noted JAWS as a comment on how this solution does not work there. A solution should then work in all. – aardrian Jul 20 '16 at 20:07
3

In case you use Bootstrap Framework there is a quick and easy solution. You should use sr-only or sr-only sr-only-focusable Bootstrap's CSS classes in a span element where your screen-reader-only text will be written.

Check the following example, a span element with class glyphicon glyphicon-shopping-cart is also used as cart icon.

<div id="myCoolDiv">
<h5>
<span class="glyphicon glyphicon-shopping-cart"></span> 2  
<span class="sr-only sr-only-focusable" tabindex="0">shopping cart items</span>
</h5>
<div>

Screen Reader Output: "two shopping cart items"

You can find the above working example in this: Fiddle

As suggested by Oriol, in case you don't use Bootstrap Framework then simply add the following in your CSS file.

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}
.sr-only-focusable:active,
.sr-only-focusable:focus {
  position: static;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip: auto;
}
Community
  • 1
  • 1
  • 4
    If you don't use bootstrap, you can go to [its stylesheet](http://getbootstrap.com/dist/css/bootstrap.css) and copy the `.sr-only` styles. – Oriol Jul 17 '16 at 18:46
  • i'm aware of the sr-only attribute, but that will hide the div. For my purposes, I need to have a visual indicator showing the div that is being read by a screen reader. – Kode_12 Jul 17 '16 at 18:50
  • @Kode_12, you could combine `sr-only sr-only-focusable` classes to show the text on focus –  Jul 17 '16 at 23:08
3

According to the text alternative computation algorithm of the W3C and the Accessible Name and Description: Computation and API Mappings 1.1 you definitely should use aria-label.

That being said, it does not work with Jaws. Text alternative is only computed for elements having an ARIA role.

The remaining option is to use a link that will go to your cart page, using both title and aria-label to satisfy anyone:

<a href="#cart" title="2 shopping cart items" aria-label="2 shopping cart items">2</a>

You can also use a transparent 1 pixel option:

2 <img src="pixel.png" height="1" width="1" alt="shopping cart items" />
Adam
  • 17,838
  • 32
  • 54
2

No, there is no equivalent to an alt attribute for <div> elements.

For what you are trying to do, an ARIA-based solution is overkill. Not only are you bumping into screen reader compatibility problems, you are applying ARIA attributes where they are not needed (and arguably do not belong if on something like a <div>).

Instead, consider using an off-screen technique (such as this one from The Paciello Group or this one from WebAIM). Content hidden using this technique will still be read by screen readers but will be visually hidden.

From reading your question, I think this is what you are after.

I made a pen demonstrating this technique. It may be easier to test in the full-page version.

Edit: Added HTML and CSS from the example, but please note that both the specs and browser / assistive technology support change over time, so if you are reading this in a year you should continue to use the links above to verify this CSS is still the current best practice.

HTML

 <div tabindex="0">
  <span class="offscreen">Items in shopping cart: </span>2
 </div>

CSS

.offscreen {
  position: absolute;
  clip: rect(1px 1px 1px 1px);
  /* for Internet Explorer */
  clip: rect(1px, 1px, 1px, 1px);
  padding: 0;
  border: 0;
  height: 1px;
  width: 1px;
  overflow: hidden;
}
aardrian
  • 8,581
  • 30
  • 40
  • I'm aware of the "hidden" divs to accomplish this, but that doesn't help me. The screen reader should be reading what is in the FOCUSED element. Therefore if I have a hidden div the screen reader will not have a visual indicator of what is being read – Kode_12 Jul 19 '16 at 22:03
  • I am confused, what do you mean by "visual indicator?" We are talking about a screen reader, so is this visual indicator intended for the developer? – aardrian Jul 19 '16 at 23:13
  • When a focusable element receives focus, the native browser visual indicator is to wrap that div with a dotted border. So If I have a div that produces , say a number, the screenreader will read that number when it has focus. But if I were to include a hidden div for the screenreader that includes more description of what that number represents, it would require tabbing to that div (although it remains hidden) for the screenreader to read. For my purposes, I'm looking for a way to include a description of the div WITHIN the focused element, not create an extra. I hope that clarifies things – Kode_12 Jul 20 '16 at 01:54
  • That visual indicator does nothing for screen reader users. Regardless, the visually hidden nested child of the `
    ` is read. If you feel that it must receive focus for a screen reader to hear, it doesn't need to. However, if you are adamant, then just put `tabindex=0` on the `
    `. Regardless, I added a `tabindex`. Have you tested it in JAWS? It performs as you specify. It announces the nested text.
    – aardrian Jul 20 '16 at 02:42
  • For some screenreaders users who are not blind, that might be disturbing to lose the visual focus indicator (cognitive problem, dyslexia, partially sighted people). – Adam Jul 21 '16 at 07:11
  • I agree, removing visual focus indicators is always a bad idea (and WCAG violation, so I should have said _blind_ SR users). However, the content is in a `
    `, not a natively focusable element. If the content needs to be focused (via the tab key, for example), then the `tabindex=0` will do that as I said above. Or put the content in a natively focusable element. Either way, the off-screen technique still works. Again, [the CodePen example](http://s.codepen.io/aardrian/debug/JKpVyL) shows this working and focusable.
    – aardrian Jul 21 '16 at 13:18
  • Please attach your example to the answer for the stackoverflow community, thanks – Kode_12 Jul 24 '16 at 22:03
1

Accessibility (Screen readers) can be achieved through role and aria-label tags on div. This can be very useful while using svg.

<div role="img" aria-label="I can speak the text">
  <svg>...</svg>
</div>
Akhil Ramani
  • 391
  • 4
  • 6
0

Use an image inside the div that has the label as its alt attribute. That way, those without screen readers just see the number and an image, whereas those with readers will hear the whole sentence:

<div>
    <img src="http://tny.im/57j" alt="Shopping cart items" />
    2
</div>

Seen as: Shopping cart items 2

Read as: "Shopping cart items: 2"

The alt attribute exists for images because there is no way to "read aloud" the content of the image, so the provided text is used instead. But for the div, it already contains text and images. Therefore, if you want it to be read by a screen-reader, you need to include the text and alt text in the content of the div.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
rvighne
  • 20,755
  • 11
  • 51
  • 73
  • i was merely using the shopping cart as an example, i need a simple div without images to render – Kode_12 Jul 14 '16 at 17:49
  • @Kode_12: I see. If you don't need any image, then [@zer00ne's answer](http://stackoverflow.com/a/38380376/1079573) is probably what you want; otherwise, this is the simplest solution – rvighne Jul 14 '16 at 18:03
0

Try:

HTML

<div id=myCoolDiv tabindex="0"><span class="aria-hidden">shopping cart items</span>2<div>

CSS

.aria-hidden {
  position: absolute;
  left: -100000px;
}

This will announce the text inside the span. And the Parent div will not lose visual focus. Aria-hidden class will hide the span from the visible screen area but will read it as its inside the div that has focus.

UIPassion
  • 120
  • 7
  • Why not using {display:none; speak: normal;} ? (Instead of putting the element out of the screen) – miguel-svq Jul 20 '16 at 19:34
  • That a good suggestion. But element with display: none; will not be read by some screen readers. For instance, I tried this approach in chrome with Vox reader extension. It wasn't read.Hiding it from the screen is a sure shot approach. To hide we can also use hidden attribute on the span.. But even that wasn't read by NVDA. – UIPassion Jul 21 '16 at 00:58
0

You can create a class such as screen-reader-text with the following css:

.screen-reader-text { 
   clip: rect(1px, 1px, 1px, 1px); 
   height: 1px; 
   width: 1px; 
   overflow: hidden; 
   position: absolute !important;
}

Then, in your code, you can just add a <span> with the screenreader text as so:

<div>
I am a div!
<span class="screen-reader-text">This is my screen reader text</span> 
</div>

See an example over here: https://jsfiddle.net/zj1zuk9y/

(Source: http://www.coolfields.co.uk/2016/05/text-for-screen-readers-only-updated/)

Ashwin Ramaswami
  • 873
  • 13
  • 22