Prior discussion for tabIndex IDL attribute can be found in #1786. But as far as I can see, that isn't an issue anymore (can be closed?). Specifically:
Chrome / Safari always return -1 for HTML elements that are not focusable (even after setting tabIndex to something else).
Major browsers all seem to reflect the values consistently now.
Current behavior of tabIndex
Test page: https://html-is.glitch.me/tabindex.html
UA/Results:
Spec
The tabIndex IDL attribute must reflect the value of the tabindex content attribute. Its default value is 0 for elements that are focusable and −1 for elements that are not focusable. https://html.spec.whatwg.org/#dom-tabindex
So my first question is: what determine "elements are focusable"?
@domenic kindly pointed out that there is specification for focus. However it is unclear if this would/should be the "focusable" definition for tabIndex?
In the focus specification, it mentions that "specifically focusable", "being rendered", and "actually disabled" are some of the characteristics considered when determining "focusable". As far as I can see, across the board, tabIndex do not consider them.
a without href is (theoretically) not "specifically focusable", but tabIndex is 0.
button[hidden] is (theoretically) not "being rendered", but tabIndex is 0.
button[disabled] is "actually disabled", but tabIndex is 0.
Motivation
Web developers often want to manage focus manually, most commonly in the case of the "tab trapping" behavior required for dialog patterns. To trap tab within a container, we will need to be able to tell what elements are indeed "focusable", but there is currently no easy way to do this. tabIndex is the closest thing we have, but not close enough.
For example, this is what we currently would need to do (non-exhaustive):
function focusable(el): boolean {
return el.tabIndex >= 0 &&
(el.tagName !== 'A' || el.hasAttribute('href')) &&
(!el.type || el.type !== 'hidden') &&
!el.disabled && !el.hidden &&
!el.closest('[hidden]')
}
If tabIndex isn't suitable for this use case, it'd be great if we can get a isFocusable() check on elements. I'd be happy to open a new issue as needed once tabIndex's focus determination rule is clarified.
Prior discussion for
tabIndexIDL attribute can be found in #1786. But as far as I can see, that isn't an issue anymore (can be closed?). Specifically:Major browsers all seem to reflect the values consistently now.
Current behavior of
tabIndexTest page: https://html-is.glitch.me/tabindex.html
UA/Results:
Spec
So my first question is: what determine "elements are focusable"?
@domenic kindly pointed out that there is specification for
focus. However it is unclear if this would/should be the "focusable" definition fortabIndex?In the focus specification, it mentions that "specifically focusable", "being rendered", and "actually disabled" are some of the characteristics considered when determining "focusable". As far as I can see, across the board,
tabIndexdo not consider them.awithouthrefis (theoretically) not "specifically focusable", buttabIndexis0.button[hidden]is (theoretically) not "being rendered", buttabIndexis0.button[disabled]is "actually disabled", buttabIndexis0.Motivation
Web developers often want to manage focus manually, most commonly in the case of the "tab trapping" behavior required for
dialogpatterns. To trap tab within a container, we will need to be able to tell what elements are indeed "focusable", but there is currently no easy way to do this.tabIndexis the closest thing we have, but not close enough.For example, this is what we currently would need to do (non-exhaustive):
If
tabIndexisn't suitable for this use case, it'd be great if we can get aisFocusable()check on elements. I'd be happy to open a new issue as needed oncetabIndex's focus determination rule is clarified.