How does tab-press work in HTML page - html

I got some problem when user pressed the TAB-key. There should be a static way in which the user can jump from one form element to the next.
I know there is a posibility to declare in which order the elements should be selected with TabIndex.
Now I would like to know how does the browser decide which element is focused as next Element after pressing Tab.
EDIT: Does it only walk down the dom or does look it on the position on rendered Website, that's what i want to know.

The process of deciding in which order to skip from one focusable element to the next is fairly complex. The first step is to find out, which elements may gain a tab focus.
There is an article by Maks Nemisj that covers your question in length: “Focus, tabIndex and behavior of browsers”.

Related

self disable button, accessibility

is there a way to don't read 'unavailable' or 'dimmed' in a self-disable-button?
See the example Example
var saveBtn = document.getElementById("saveBtn");
var helper = document.getElementById("helper");
var content = document.getElementById("content");
saveBtn.onclick = function(e) {
saveBtn.setAttribute("disabled", "disabled");
saveBtn.setAttribute("aria-disabled", true);
content.innerHTML = 'Lorem input a lot of stuffs';
helper.innerHTML = "Content added, please read it";
setTimeout(function(){
helper.innerHTML = "";
saveBtn.removeAttribute("disabled");
saveBtn.setAttribute("aria-disabled", false);
}, 5000);
};
Voice only says: 'Content added, please read it'
NVDA says: 'Content added, please read it. Unavailable'
I know that it is happening because the button still having focus. But, I need to find a solution for that because I can't modify the current behavior of my page.
I'm using the html helper to inform transitions as you can see https://stackoverflow.com/a/38137593/3438124.
Sorry for ugly code, this is only to simulate my real behavior.
Thank you guys!
You will need to move focus to the new element. Give it tabindex=0 and then use focus().
aria-live is for when you want to have the screen reader speak changes for the content area with the aria-live attribute. Since you use it on a sibling div, you are missing the opportunity for it to just do what it does. Alternative, you can skip the tabindex/focus() approach and just put aria-live on a container for your new content.
Also, you can ditch the aria-disabled and just lean on disabled for the button. aria-disabled is for elements that otherwise do not support disabled.
You answered your own question when you said "I know that it is happening because the button still having focus" and then aardrian pointed it out explicitly when he said "You will need to move focus to the new element".
Keep in mind, though, that whether the focus remains on a disabled object is totally up to the user agent (browser). Some browsers leave the focus on the disabled object and others move it to the parent.
aardrian's comment about using tabindex was if you wanted to move the focus to an object that is not normally focusable (ie, if it's an element you can't normally TAB to). So if you want to move the focus to some simple text (just to get it off the button), then I'd tweak aardrian's suggestion and use tabindex='-1' instead of tabindex='0'. That will allow you to call focus() on that element but won't allow the user to TAB to it.
If you want to move the focus to another button on the page, or some other element that can naturally receive focus (checkbox, input field, etc), then you don't need tabindex.
If you end up moving the focus to the text that was just added, then you don't really need aria-live because the screen reader will read the text that you just focused to. But that's only relative to the example you posted, which I understand is just a sample to show the problem. Your real app might not be adding text.
And I want to second aardrian's recommendation of not setting aria-disabled when you're already using the disabled property. It's superfluous. The aria-disabled property is for when you're simulating a disabled object.
How the text is read varies reader to reader. None is right or wrong. If you want the text being read out to be same and consistent across the readers..Do a little workaround. Add an aria-label="desired text" to your button. This will override anything that is present inside the button tag.
eg
<button aria-label="desired text button">This text will be ignored</button>
Nvda will read the button as "desired text button". Text inside button is ignored. Now you can handle(add/remove) the disabled and aria-label attribute with JS.
In the context of your question you can try:
Instead of:
helper.innerHTML = "Content added, please read it";
Try using:
saveBtn.setAttribute("aria-label", "Content added, please read it.");
setTimeout(function(){
saveBtn.removeAttribute("aria-label");}, 5000);
Then the text will be same across the readers.

Is there a way to inform the screen reader about a transition to a new section on the same page?

I have a page that has 2 steps to register a user.
After a user has filled out all fields of the first section, he needs to confirm the "Terms and Conditions" and press a button to confirm it.
After he has pressed the button, first section is becomes readOnly and the second section (more fields to fill) appears at the bottom of the page and the page does a scrollTo this new section.
I need to inform the screen reader that there is a new section on the same page but I don't know who can I do it.
I appreciate your help!
In your html have an empty span/div with aria-live="assertive". In your button click function, add the text you want the reader to announce to that span.
(This is the same function where you will be taking focus to that section.)
Don't forget to empty it outside the function to make it announce properly next time also.
Aria-assertive text will be announced each time it is changed.
Eg.
In HTML
<span id="announce" aria-live="assertive"></span>
<button id="btn">Click</button>
In javascript
$("#btn").click(function(){
$("#announce").text("Scrolled to a new section");
});
This is about focus management. You need somewhere to anchor focus that makes sense to the user and you need to then move that focus.
This is not an ideal solution overall, but lacking context for the larger objective I'll give you the bits to get this part functional / useful.
First, add this style so you can see where the focus is going (you can remove/change it later):
*:focus {
outline: 2px solid #f00;
}
Now as you tab through the page you can see where the focus lives.
Then in your script where you create the new form (I recommend you actually just hide this section and display it instead of writing it in via JS, but I understand this may be a demo), update the <h3> to be focusable by adding an id attribute and then a tabindex so that you can drop focus on it. I use the <h3> you already have since it provides the context for the user and in this case overrides my general distaste for using tabindex on non-interactive elements.
<h3 id="second" tabindex="0">
Then add bit of script after your setTimeout() that moves the focus to that element (thereby ensuring it has been rendered and can receive focus):
var secondForm = document.getElementById('second');
secondForm.focus();
Now when you click the "Continue!" button, the page scrolls and the heading will receive focus, get announced (you can add instruction text, etc), and the user may continue.
You will probably need to massage the script a bit, maybe stuffing it in its own timer function to be certain it only fires when you want, but overall the general concept is in there.
I made a pen to demo it.

Focus is changed when inspecting element with CTRL+SHIFT+C

When I want to inspect an element in the browser with either CTRL-SHIFT-C or by clicking , the current focus is changed, possibly leading to elements that was previously visible not being visible any longer.
Is there some way of avoiding that?
You can select the element you need focus on in the Elements panel. Then find the :hov toggle (As of V49 iirc, 48 may still be a thumb-pin icon) which will open a menu for toggling given element states. From there, just select the one you need applied (focus in this case.) That will force the given state even if focus is somewhere else.

How to make a custom web component focusable?

I'm writing a custom web component that is meant to be interactive. How can I tell the browser that this custom component should receive focus?
I wish that my custom element…
could be focused (by tab-navigation);
could receive keypresses when focused;
could be matched by :focus pseudo-selector.
I'm not using any external library, just plain HTML5 APIs.
Based on this demo that I found in this question, I have this answer:
Just add the tabindex attribute to the elements you want to be focusable.
// Add this to createdCallback function:
if (!this.hasAttribute('tabindex')) {
// Choose one of the following lines (but not both):
this.setAttribute('tabindex', 0);
this.tabIndex = 0;
}
// The browser automatically syncs tabindex attribute with .tabIndex property.
Clicking on the element will give it focus. Pressing tab will work. Using :focus in CSS will also work. keydown and keyup events work, although keypress doesn't (but it's deprecated anyway). Tested on Chrome 44 and Firefox 40.
Also note that this.tabIndex returns -1 even if the HTML attribute is missing, but this has a different behavior than setting tabindex="1":
<foo></foo>: No tabindex attribute, the element is not focusable.
<foo tabindex="-1"></foo>: The element is not reachable through tab-navigation, but it is still focusable by clicking.
References:
http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute
https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
https://github.com/whatwg/html/issues/113
#Denilson, I would like to provide you with some more information.
As you said, this.tabIndex = 0 works when your webcomponent contains no focusable elements. If it does, it gets more complicated.
For example, if your component contains one or more inputs, then first the "whole" component gets focus, and only later, when tabbing, each inner inputs get focus, one by one. This is usually not what you want. Usually, when the component gets focus this should mean its first input gets focus immediately.
Also, there is a reverse tabbing problem. If your first input has focus and you press SHIFT-TAB, then the "whole" component gets focus, and you are forced to press SHIFT-TAB twice to move to the previous element.
I found this to solve all focus and tabbing problems:
// At first, the component may get focus and accept tabbing.
createdCallback = function () { this.tabIndex = 0; }
// When the component gets focus, pass focus to the first inner element.
// Then make tabindex -1 so that the component may still get focus, but does NOT accept tabbing.
focus = function (e) { firstFocusableInnerElement.focus(); this.tabIndex = -1; }
// When we completely left the component, then component may accept tabbing again.
blur = function (e) { this.tabIndex = 0; }
Note: As of now (Sep 2015) if an inner element gets focus, then the "whole" element is not matched by the :focus pseudo-selector (tested only in Chrome). If find this behavior to be just plain wrong. The focus event was fired, and the blur event was not. So the element should have focus, right? I hope they change this in the future.
Short answer: delegatesFocus is what you need here, not tabindex.
Details:
Assuming that you have interactive elements inside the shadow DOM, there is no satisfying way to make the component programmatically focusable with tabindex:
if you set it to 0 you add the host element to the tab sequence ("sequential keyboard navigation") and you have an extra tab stop
if you set it to -1 you remove not only the host element but any interactive element inside its shadow DOM from the tab sequence, so the whole thing becomes inaccessible for keyboard users
There's a web component API just for this: ShadowRoot.delegatesFocus, see here. Set this to true and you'll get:
calling .focus() on the host or clicking on any non focusable part of the component focuses the first focusable element in the shadow DOM
:focus styles are applied to the host in addition to the focused element within
tab sequence is unchanged (it should already work the way you want)
It's supported since shadow DOM v1.
One very pragmatic approach I use, if possible and suitable, is just to put a <button type='button'> around my custom element.
This maybe does not fit as solution for you, I mention it anyway for others stepping into this question / problem.
It handles all focus matters, including a focus rectangle an so on.
To tame a <button> is less work than it seems (think especially about the line-height the button changes)

Where focus should be set if HTML element removed?

I have HTML (simplified) like this:
<ul>
<li><a id="1" onclick="removeItself(1)" href="#">first</a></li>
<li><a id="2" onclick="removeItself(2)" href="#">second</a></li>
</ul>
<input type="text"></input>
If the one of the links is clicked it will be removed. In my case after removing, the whole list will be rendered again.
There are many questions, but the general is where to set focus if element with focus is removed?
Where should be focus set if e.g. the second list element is removed or if all elements are removed?
What solution is web-accessible in this case? Is it acceptable to set focus always on the first item in the list, but if all items are removed to set focus to the next (input) or to a previous element?
In IE the focus will be reset and it will start from the beginning of the page.
The general principle I would apply here is:
if a next element exists, place the focus on the next element,
otherwise, if a previous element exists, place it on the previous element,
otherwise, place it on some element before or after that makes sense, of there is none, then do nothing
Here is the Angular.js TodoMVC application that I have modified to behave this way (although you could argue that I have not done a good enough job on #3 from above)
http://dylanb.github.io/todomvc/index.html#/
Here is a blog post on the process of making the delete work
http://unobfuscated.blogspot.com/2015/02/angularjs-accessibility-deleting-todo.html
This is what I did based on the answer for question Where to put focus after deleting an item in a list
Following the principle of Least Surprise, I would leave the space open with "[deleted]" in it til the cursor moves off the list, at which point the gap can be closed.
Given:
Say there are 3 items in a list and user uses up / down arrow to navigate and focuses on the second one.
User Action:
There is a delete button inside the list item, user tabs onto it and presses enter.
Context Feedback:
After deletion succeeded, focus will be placed on an invisible item at the original place where the second item was, and this invisible item contains text "Deleted" (screen reader will announce "Deleted").
Clean Up:
Then user can still use up / down to move focus to the previous / next item (or what you implemented before), and invisible item would be removed after onblur event triggered.