Problem: I have a div that is nested inside a span tag with the role of button, whenever the span button is focused, what I want to have happen is the screen reader 'read' the text in the nested div --> p tag when the span receives focus
<span role="button" tabindex = 0>
<div id= "nestedDiv" aria-hidden ="false" tabindex = 0>
<p tabindex =0> Read this text </p>
</div>
</span>
I tried different screenreaders and different browsers, same issue, it doesn't read the div, it just skips over to the next readable element.
I tried this in NVDA + firefox and it reads "read this text. button" when I tab to the span. Which browser are you having trouble in?
You could try adding an ID to the paragraph such as <p id="foo"> and add aria-labelledby="foo" to the <span>.
However:
Karl Brown's comment is 100% accurate - it's best to use semantic markup. Does the span do something? If so, it should be a button. Does it bring you to a different page? If so, it should be an anchor.
Also, why so much tabindex? It takes three tabs to get outside of this element, which is not good. If you use proper semantics you wont need tabindex and you wont need any aria attributes.
Related
Which is the correct way to make inline tooltips accessible?
I have 2 versions below.
Version 1: Use the title attribute. When hovering I will use JS to hide the title attribute and add the text to my custom tooltip. I will add back the title attribute when hover is off.
<p>For here am I sitting in a <span title="A spaceship">tin can</span> far above the world planet earth...</p>
Version 2: use aria=label and role="tootlip"
<p>For here am I sitting in a <span aria-label="A spaceship" role="tooltip">tin can</span> far above the world planet earth...</p>
Note: this question is for inline tooltips only, meaning the tooltip text is in the attribute of the element which triggers the tooltip. The tooltip is not separate from the element triggering it.
The title attribute by itself does not reliably provide an accessible name for the element, meaning it will not be read by all screen readers.
Aria-label has no function if it is not assigned to an interactive element. Beware also, that the aria-label replaces the element’s content from an accessibility perspective.
Since you want to use that attribute only to inject another element with that text as its content, the issue here is more one of confusion, and it might be better to use a non-semantic attribute in that case like data-tooltip.
The aria-label attribute defines a string value that labels an interactive element.
Which brings us to another aspect: The tooltip needs to work with touch screens and keyboard, too. So it will need to be focusable and focus needs to be visible. A tooltip should also be closable by means of Esc.
A tooltip is a popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it. It typically appears after a small delay and disappears when Escape is pressed or on mouse out.
https://www.w3.org/WAI/ARIA/apg/patterns/tooltip/
Since aria-describedby is recommended for screen readers to reference the additional contents, it is better to have that element already in the DOM, which would simply be hidden or shown depending on tooltip state.
<p>For here am I sitting in a <span aria-describedby="tooltip-spaceship" tabindex="0" role="tooltip">tin can</span> far above the world planet earth...
<span id="tooltip-spaceship" hidden>A spaceship</span></p>
Lastly, the least expensive way, which is easier to use as well, is to simply provide them in the text at their first occurrence:
<p>For here am I sitting in a <dfn>tin can</dfn> (a spaceship) far above the world planet earth…</p>
See also Understanding Success Criterion 3.1.3: Unusual Words
I am trying to optimize a few components for screen readers, however Android Talkback proves to be a challenge....
Here is a very simplified example for the code:
<div class="wrapper">
<form>
<span role="presentation" aria-hidden="true">
This should not be read by Talkback
</span>
<input aria-label="This should be read by Talkback" />
</form>
</div>
The text inside the span is updated dynamically, and is positioned absolutely over the input - just to appear like an animated placeholder, without actually being read by screen readers. That is what the aria-label is for. However, TalkBack still seems to recognize the span - so it reads the content of the aria-label first, then continues reading the text in the span... role "presentation" or role "none" did not prevent this, neither did moving the text even further from the input. (For example, outside the form). Is there any way to prevent this?
The role attribute only changes the type of element that Talkback and other screen readers announce. Setting it to presentation or none just removes the semantic type of element. A <span> does not have a native role by default so it's essentially presentation/none implicitly and won't have any effect.
aria-hidden is the key. It will hide the element from the screen reader. (CSS display:none and visibility:hidden will also hide an element from the screen reader but it also makes the element invisible to sighted users too.)
Your code example should work just fine with Talkback. However, you mentioned that you dynamically change the contents of the <span>. That's not a problem but is there a chance that when you updated the text, the aria-hidden got removed?
I have used aria-hidden on Android without any trouble.
The solution in my example was already enough to fix the issue.
aria-hidden prevents the span being focusable, and if the span is located before (and not after), TalkBack will not interpret the text as being part of the input.
To make a span into a clickable link.
I have made a span that contains only a background image (as part of a Gilder/Levin image replacement technique) into a clickable link, and it seems to work fine -- but, so far, that is only on my own desktop computer, and on Chrome, Opera, and IE 11.
Is this viable?
<div id="logo">
<a href="[absolute url]">
<span></span>
</a>
<h1>page name</h1>
</div>
It works on my computer, with Chrome, IE11 and Opera. Will it work universally?
While it might look okay in most browsers, you're using the <a> element incorrectly, as what goes inside it should be a meaningful label. The proper thing to do would be to wrap the entire <h1> in the link, or to put the <a> within the <h1> (both are valid HTML5).
<a href="[absolute url]">
<span></span> <h1>page name</h1>
</a>
But judging from your comments, it's probably too early for you to start worrying about image replacement techniques an web semantics when you're still figuring the syntax out.
What's the point of image replacement techniques and why using an empty <a> tag is bad?
The Gilder/Levin image replacement technique involves adding non-semantic elements to a page (such as <span> elements) and using CSS to replace them with icons, so that these elements are ignored by screen readers. After all, an icon next to a menu button might make the button more visible for someone who can see, but the icon becomes redundant when you're blind and are using a screen reader which will read the text of the button out loud anyway. This also might make your website easier to parse by search engines.
However, in the original code, you didn't put any label on the link (actual text between the <a> and </a>), therefore making it especially confusing for screen readers and robots to know what this link is supposed to be. The entire title should be within the <a> element in this case, allowing the whole line to be clicked to follow the link. It's definitely not a good practice to use an empty <a> element, and the fact that there is a <span> within it changes nothing.
And since the idea of leaving an <a> element is semantically absurd, I haven't found any reliable place documenting the behavior of such an element across browsers.
wasn't pretty sure what you are asking for:: or trying to achieve.
3. wrap span in a href tag.
2. span onclick() function with javascript
1. span:hover with css.
<div id="logo">
<a href="[absolute url]">
<span>this span is now like link text.</span>
</a>
<h1>page name</h1>
</div>
<div id="logo">
<span onclick="myFunction()">this span is now like link text.</span>
<h1>page name</h1>
</div>
<style>
span:hover{color:red;}
span:active {color:green}
</style>
The css one isn't really click stuff.
Yes, it's a reliable way to put <span> or <img>(or any element you want to be a link) in a <a> tag.
click here for Definition and Usage
The tag defines a hyperlink, which is used to link from one page
to another.
The most important attribute of the element is the href attribute,
which indicates the link's destination.
I have anchor tag defined as below:
<a href="www.abc.com">
<div tabindex="0" aria-label="XXXX">
...
<div>
</a>
Currently, the screen reader reads the content of href in <a> tag. However, I don't want the href to be read, but the content in the aria-label in the div.
I would like to know what is the right way to achieve the goal?
Your <div> does not have any semantic meaning so the aria-label will essentially be ignored. See https://www.w3.org/TR/using-aria/#label-support. Specifically, the third last bullet point:
Don't use aria-label or aria-labelledby on a <span> or <div> unless its given a role.
You do not want tabindex="0" on an element that is not actionable/interactive.
Just put your aria-label on the anchor itself:
<a href="www.abc.com" aria-label="XXXX">
Note that if there is any visible text in your anchor link (you have "..." in you sample code so I wasn't sure if there was any text there), make sure the aria-label contains that same text, plus any additional text that you want. If you don't, then speech interface users may not be able to select your link.
remove aria-label from the elements or you can use aria-hidden="true"
Screen reader cannot read me
To know more about this check here
Add the attribute aria-hidden=“true” to the <a> to hide it from screen readers. That will hide its child elements as well, so add aria-hidden=“false” to the <div> to un-hide it.
I have a div element with role="listitem". It contains multiple divs with some text inside. When he outer div is focused, I want a custom aria-label to be read instead of the inner texts. Here is my sample code:
<div role="listitem" aria-label="Hello World" tab-index="0">
<div> A </div> <div> b </div> <div> c </div> <div> d </div>
</div>
On JAWS and Narrator, it works as expected. On NVDA, it's reading the inner text.
On changing outer div to anchor tag, NVDA is reading correct aria-label, but I cannot do that in prod code.
NVDA seems to honor the aria-label for some roles but not others. It works for button and menuitem, it reads both the aria-label and the nested <div>s for checkbox, and ignores aria-label for listitem, as you mentioned.
This seems to be a current bug. See https://github.com/nvaccess/nvda/issues/7807