For iOS, Safari, VoiceOver, how do I get VoiceOver to read something other than the text content?

12,863

Solution 1

You can use aria-label like this:

<span tabindex="0" class="myClassName" id="DateLabel" role="heading" aria-label="1 0 2 am">1:02a</span>

However, why are you setting tabindex to 0? For a heading this is not a good practice because screen reader users can navigate between headings using the keyboard commands. Also, you will want to set aria-level on your heading to indicate what level it is.

The best markup to use for this is:

<span class="myClassName" id="DateLabel" role="heading"
aria-level="2" aria-label="1 0 2 am">1:02a</span>

Update: This appears to no longer work for at least some versions of VoiceOver, it will read the visible content and ignore the aria-label. See this bug - https://bugs.webkit.org/show_bug.cgi?id=160009

Solution 2

In my case I used for iOS VoiceOver:

<span role="text" aria-label="audible text">visible text</span>

it is important to add the attribute role="text" so that VoiceOver reads the attribute aria-label=""

Solution 3

You could use the abbr html element.

For example :

<abbr title="HyperText Markup Language">HTML</abbr>

Solution 4

In this case you could use a pattern that hides the visual text from screen-readers and hide the screen-reader text from showing visually. Like this:

<span aria-hidden="true">1:02a Dec</span>
<span class="visually-hidden">1:02 AM December</span>

and use CSS to hide .visually-hidden for example like this:

.visually-hidden {
  position: absolute;
  left: -999em;
}

Don't use display:none since it removes the element from being sent to the accessibility API.

As a side note: use role="heading" carefully if ever, and if so use an appropriate aria-leve="#" number/level.

Share:
12,863
Admin
Author by

Admin

Updated on June 05, 2022

Comments

  • Admin
    Admin almost 2 years

    I am trying to get VoiceOver to say something other than the specified text content in an HTML span element:

    <span tabindex="0" class="myClassName" id="DateLabel" role="heading">1:02a</span>
    

    Consider the case where I might like VoiceOver to say the full time text.

    When I add the aria-label attribute, VoiceOver is still reading the text, despite desktop browsers like IE and Chrome correctly reading the aria-label instead.

    When I add the aria-labelledby attribute plus a hidden aria label element, I am able to get VoiceOver to read the alternate narration, and NOT the text content. However, I find this only works if the aria-role is a widget role like button or link. This is bad because I don't want to imply to users that this is an interactive element they can activate. VoiceOver annoyingly appends "button" to the end of the narrated sequence. I would prefer to use a structural role like "heading" but then VoiceOver just reverts reading the text content instead of reading my hidden narration.

    Please help! I've been bashing my head against this but I simply cannot stand iOS's non-standard implementation of ARIA. I don't understand why they must be different from desktop browsers for something so simple but they are in so many places and I cannot find a good document outlining the exact behavior anywhere.

  • slugolicious
    slugolicious almost 10 years
    I think Daniel meant to say role=heading instead of aria-heading. Headings are very powerful to assistive technology users because screen readers such as VoiceOver or JAWS allow the user to navigate by headings so it's very fast to move around the screen. You don't necessarily have to use aria-level when using role=heading. If you want to mimic an <h2> tag, then yes, you need aria-level=2. However, if you are displaying a scrollable list of choices where the choices are grouped together (such as the <optgroup> does), then you don't want the aria-level set. You just want role=heading.
  • Daniel Göransson
    Daniel Göransson almost 10 years
    @slugolicious Thanks, that's exactly what I meant :) and good point about omitting aria-level on for example <optgroup>
  • launchoverit
    launchoverit almost 8 years
    This fails for me. Using this markup - <span aria-label="the audible text">the visible text</span> VoiceOver reads "the visible text"
  • unobf
    unobf almost 8 years
    @launchoverit that is because you did not use all of the markup I specified. The role="heading" is important because despite aria-label being allowed by the spec on any role, it only works on some roles at the moment. Also, if you downvoted this because you did not use all the markup specified, then that is not cool.
  • launchoverit
    launchoverit almost 8 years
    Thanks for the clarification about role, I had tried your full markup as well but without success, so I thought posting a more basic markup would simplify my point (obviously wrong about that, sorry). Here’s a codepen with your markup, it still reads “the visible text” for me. codepen.io/anon/pen/dXdEXx.
  • unobf
    unobf almost 8 years
    looks like this has broken in some version of VoiceOver. I get the rotor showing "the audible text" while VO still speaks "the visible text". This is obviously a regression.
  • launchoverit
    launchoverit almost 8 years
    Thanks for checking. What's most helpful for this answer at this point? Would an edit to indicate that this no longer works be helpful? I'm happy to add it if you want.
  • unobf
    unobf almost 8 years
    I have reported a bug to Apple bugs.webkit.org/show_bug.cgi?id=160009 and we should track that. This technique still works in other ATs and is standards compliant. If you want to add information about the lack of support for this technique in VO I think that would be useful.