I have a container div whose first child element is another div which acts as a button. The container has one or more additional child elements.
The inner button div is always in the tab order. Our application has a "screen reader mode", and when that is enabled, we also include the outer container div in the tab order. The motivation for this is that we want screen reader users to be able to tab to the whole container, and hear all of the contents read out in order.
The problem is - if the user tabs to the container div and presses the spacebar, the screen reader moves the focus to the child button div, and executes the click action. This happens whether or not the button div has a role of "button". (I'm seeing this happen with JAWS and NVDA. It only happens when the screen reader is running).
Suffice it to say -- we have a complicated UI, and this introduces problems that we'd like to avoid.
Why is this happening? Is there anything I can do to prevent it from happening? I'm open to hacky workarounds.
<div class="container" tabindex="0">
<div role="button" title="tooltip" sys:command="command" tabindex="0">
//Main Content
</div>
<div tabindex=0>
//Secondary Content
</div>
</div>
You need not and must not set the tabindex on this div. Screenreaders have other shortcuts than the tab key (which normally read through focusable elements only) to read non focusable elements.
For instance the description of the browse mode states that
In browse mode, the screen reader cursor can be placed on every element on a website, even on those which aren't inherently focusable, for example headings (<h1>, <h2>, etc.) or paragraphs (<p>).
Related
I have a situation where when a div is in focus, NVDA screen reader reads aria labels of all elements in the div.
Here is a code pen which I created to recreate this Codepen - NVDA Screen reader
There are three main div's in the HTML with class names - first-row, separator and second-row.
The div with class second-row has tabindex="0" to make it focusable. This is part of the requirement.
This div also contains 3 child div's with class - header, content and footer each one which has focusable elements with aria-label. The footer child div also has tabindex="0" which again is part of the requirement.
When the focus is on second-row or footer, the NVDA screen reader announces all contents of the div as shown below
second-row - Announced text below
footer - Announced text below
Our requirement was to not let the NVDA announce the div contents which adds to the confusion of the users.
Questions
Is this behavior correct ? Should the NVDA screen reader announce contents of a focusable div ?
I can try using aria-hidden="true" on these focusable div's but this also chains down to child elements, hence when the focus is on the child elements, the screen reader does not announce them. I can write focus-in and focus-out events to update the flag for aria-hidden, but is there any other workaround for this ?
Most of the times, when the focus reaches the first focusable element of a focusable div, NVDA does not announce anything. In the codepen example, the first input element of footer div. What could be going wrong here?
The behavior you observe is absolutely correct. When an element is focused, the accessible content has to be read entirely by the screen reader.
It's the core of its functioning, tell the user what's under focus right now.
Your fundamental problem is that you have overlapping focusable elements.
Focusable elements must never be overlapping, or otherwise said, a focusable element must never be inside another focusable element.
Doing so creates several problems, such as what you observe with confusing content read twice. But also, when the focus is in the inner element, should keyboard events still be sent to both elements ? IN which order ?
Same question when clicking on it, which element(s) should take the focus and/or send events ? One, the other, or both, will arrange you in turn depending on the situation. There is no universal good and correct answer.
Knowing if being on the inside or outside element isn't always super clear either: is it the exact shape of the text or image, taking into account transparent parts or not, or is it the entire rectangular zone ? It depends on CSS background ? And so on.
IN short, it's too easy to make insanely confusing things for the users, so you must really avoid it.
The good news for you is that your tabindex=0 appear totally useless here. You should just remove them.
An element must be focusable if, and only if interactions are possible with that element. If the element doesn't provide any interaction, then it shouldn't be focusable.
Would you focus something which you can't do anything with ? At best it's a waste of energy/efficiency/time because you have to tab once more for nothing, and at worst it's only confusion for the user, who may not realize immediately that the focused element does nothing useful. What's more annoying than writing in the void ?
Here, your divs don't provide any interaction, so they shouldn't be focusable. Remove these totally useless tabindex=0 and voilà, problem solved.
I've run into the following issue on Chrome (v. 85.0.4183.102) on macOS (10.15.5):
Occasionally, when I select a div using VoiceOver, it will read out everything contained in the div. For instance, a div with role="main" might have a header, a few paragraphs, and some links. VoiceOver will read out all of those items when the parent div is selected. I can then press VO Next to advance to the first element within the parent div and it will read that item out individually.
I cannot reproduce this in Safari. When I select the main div, it simply reads "main". I can press VO Next and it will read out the elements individually, as one would expect.
Any idea why VO is doing this only in Chrome?
I have one form which has scrollbar associated with it . page reads properly element by element but focus does not move with voiceover.
I am testing this html form in iphone 5 with ios 8.1.
The focus only moves to elements that are tab focusable. These are elements like links, buttons and input fields or elements that have an explicit tabindex attribute greater than or equal to 0. Voiceover and other screen readers will read out intervening text, but leave the focus on the most recently visited focusable element until the next focusable element is encountered, at which point the focus will jump to that element as it gets read out. This is the way it should work and there is nothing "wrong" with this behavior.
Situation:
iOS 7.1
VoiceOver is Enabled
Hyperlink (<a href="#content">) points to:
target element on the page (<div id="content">page contents</div> or <a id="content"></a>)
URL I'm investigating: http://www.yooralla.com.au/whats-on/yooralla-media-awards/yooralla-media-awards-judges-pack
What happens:
Select and activate the link
A border appears on the target element (which is halfway down the screen)
The page scrolls so that the target element is at the top of the screen, but the border stays halfway down the screen.
The closest element to the border is then selected and bordered, so reading starts halfway down the page instead of at the target element.
Closest reference that I can find to this issue is item 1 here, so maybe it is fixed in iOS 8.
But I'm trying to work out why it's happening and how to avoid it on as many devices possible. I've tried linking both to the main content div (which fills most of the page), and inserting an empty a tag, both of which behave the same.
EDIT:
I've tried to force the reading position by setting focus or scrolling with JavaScript, but VoiceOver still ignores this and reads from the wrong place.
I have a div section, which is full of tags, on a event on the page I shrink the div section BUT if the user tabs into the div section, it moves so that the highlighted <a href> has focus, is there any way to lock a div section that it's contents don't move ?
So for example the code (psuedo not real) I have the following
<div>
<h4>Heading</hv>
Link 1
Link 2
Link 3
</div>
I shrink the div section so that only the h4 is displayed {overflow:hidden}, however the user can then tab to the elements and this scroll so that they are displayed in the the div "window" which is not what I want, so in effect I get <div>Link 1<div> where what I want to remain is <div><h4>heading</h4></div> in effect I want to stop the contents of the div sectio scrolling so that the selected element is displayed. I know that if they press return the selected link will be follow, but I'm not worried about this, just what is displayed
I hope thats cleared, you can see my problem if you go to link text click on the training section on the left and then back tab (shift tab) , the article section above changes.
Thanks
is there any way to lock a div section that it's contents don't move?
Not really*, but you don't really want that anyway. Even if you locked it in place, the invisible links would still accept focus, resulting in a confusing tab behaviour.
(*: short of something horrendous like changing the scrollTop of the overflowing element from JavaScript onfocus. Ugh.)
What you should probably do is put a div around the links, and set its display style to ‘none’ when the links are elided. That way they won't participate in the tabbing order.
From what I can make of your question, you want your div to stay fixed relative to the browser window. If this is the case, it can simply be done by declaring position:absolute for the div.
If you want something else, please clarify your question.