Certain HTML elements are focusable without having an explicit tabindex attribute:
a elements that have an href attributelink elements that have an href attributebutton elementsinput elements whose type attribute are not in the Hidden stateselect elementstextarea elementssummary elements that are the first summary element child of a details elementIt would be nice if custom elements could also opt in to being focusable without having to sprout a tabindex attribute - such that if page authors removed the tabindex attribute, the element was still focusable.
It seems like this would be something that might fit in with whatever new API comes out of #758.
Strong +1.
Do you think it's worth exposing both of tabindex's capabilities here, or just one? They are:
I think there are common built-in elements whose behavior falls into each of these categories, although it may be OS dependent.
+1 and I would like to see both 😀
In all honesty, I've never understood why tabindex = -1 is a thing, other than for excluding things from the tab order - i.e. why aren't all elements programmatically focusable? What do we gain from focus() sometimes being a no-op? Who is out here trying to call focus() on a <div> and hoping it ... fails?
But that aside, I guess allowing focusable things to also opt out of the tab order is probably useful for managing focus within complex components.
@alice tabindex="-1" also affects what you can click and will get a focus ring, iirc.
@annevk True, although I've seen that cause more undesirable behaviour than desirable.
Whatever mechanism we use for tabindex should be flexible enough to default ARIA role & other ARIA attributes as well.
@rniwa Agreed, I'm hoping all of the use cases mentioned in #758, plus this one, can share the same mechanism.
Wouldn't it be great if an element became focusable just by setting its role to something that is known to be an interactive element as per the ARIA spec. Just like a button is implicitly focusable, if I set the role of an element to be a button, I would love for the browser to just take care of it for me.
I seem to recall ARIA affecting behaviour in that way was a deal breaker in the past - ARIA's contract is that it only affects accessibility tree computation.
(Edited to add:)
The reasoning being that if ARIA affected behaviour, it might discourage authors from using it.
Discussion at TPAC: We should keep in mind the concern that platform conventions differ, so we don't want to be in a position where authors can't match behaviour of the platform they are on. Consider a mode where you match some other element's behaviour...
A possible API is:
interface ElementIntenals {
attribute boolean defaultTabindexFocusFlag;
}
If the tabindex content attribute of the target element is omitted or the attribute value is not parsable, 'tabindex focus flag' is initialized with defaultTabindexFocusFlag value.
@tkent-google I think that is the simplest design that could work. (Although I would change the name to be something less spec-focused and more intelligible to authors, but that doesn't matter for now.)
However, the above discussion revealed a few other possibilities:
focusBehavesLike: "a" or focusBehavesLike: "button". Maybe we could come up with something more restrictive, like a set of a few archetypes (instead of allowing any tag name).What do you think of these considerations? Maybe they are overcomplicating things, and we should just go with the simple boolean version.
We have two categories of focusable elements in Chrome:
Elements which supports complex keyboard interaction while it's focused
Text-field INPUTs, TEXTAREA, SELECT, contenteditable
They are "Text boxes and lists" in macOS Full Keyboard Access setting.
:focus-visible and :focus have same behavior.
Elements which supports simple keyboard interaction. e.g. Spacebar works as click.
Buttons and links
They are skipped in sequential focus navigation if Full Keyboard Access setting is "Text boxes and lists only".
:focus-visible doesn't match to them if they are focused by mouse click.
If we support only these two categories, we should add a boolean flag like needsComplexKeyboardInteraction.
Do we want to support a behavior other than these two categories?
Probably, see https://github.com/whatwg/html/pull/938#issuecomment-201320851 onward for some discussion on this. It'd be good to first sort this out for existing features though, before exposing it to the world.
Well, there's a third category, right? Elements like div, which are not focusable (without explicitly setting tabindex). So I think a tri-state is necessary if we want to support the range of capabilities.
And, of those three categories, which does <div tabindex="0"> fall into? What about <div tabindex="-1">?
The big question is whether those three (?) categories of Chrome's are matched by other browsers. I am hopeful they kind of are, and the thread @annevk links to has some details I should re-read. We should try to confirm.
It would be great if we could figure out the total set of behaviors that browsers want to expose. Then we could codify that model in the spec, better than the current text, and expose it to custom elements. I don't think that'll be _too_ hard...
@domenic, yes, there are three categories if we include non-focusable. I meant categories in default focusable elements.
In Safari, the second category in my comment is not mouse-focusable even if Full Keyboard Access setting is "All controls".
Behavior of overflowed elements and <video controls> may be implementation bugs which we should fix.
tabindex attribute should override the default focus behavior, right?
In Safari, the second category in my comment is not mouse-focusable even if Full Keyboard Access setting is "All controls".
Interesting! Maybe it's a bit early to start guessing at APIs, but this could point toward a setting like matchFocusBehaviorOf: which is allowed to be one of "input", "button", "div". Or maybe focusBehavior: "text entry", "clickable", "none" to be more abstract.
tabindex attribute should override the default focus behavior, right?
Yep! I am just hoping that div-with-tabindex falls into those two categories, not some new category.
I think the challenge here is designing this API to be future proof. We don't want to hard code what's exactly needed for existing platforms because that'd limit future platform that we can't even imagine exist today.
Yeah, agreed. I think we can do that by using an enum instead of a boolean (and it looks like there will be 3+ options anyway). We can then expand that as needed.
Would you be able to confirm the categories of behaviors currently present in Safari?
Safari's behavior is that by default only form controls are tab focusable. Option + tab would focus every element that's focusable by default like link elements. Separately, every non-editable form element like buttons or input[type=submit] is not mouse focusable. In order to correctly describe WebKit's behavior, we'd need to be able to differentiate four states:
Note that the user can override the behavior of tab key to be more like option+tab in Safari's preferences.
we can do that by using an enum instead of a boolean
I think enum value is problematic because that would mean that whenever a new platform shows up, or the platform convention changes, websites may need to adopt the change. Also, I don't think hard-coding the list of things Safari do today to the web platform is a good idea either. Specifying relative to builtin elements is an interesting idea although it's hard to differentiate editable input from non-editable input but perhaps input is an odd case due to its behavior completely changing based on type attribute.
TPAC 2019 discussion: https://www.w3.org/2019/09/17-components-minutes.html#item07
It mentioned possibility of borrowing concepts from ARIA. Does it mean using ARIA roles as high-level concepts?
Apologies for the long comment. Hopefully it's at least clear.
I think there are three fundamental states for focusability: an element is
<div>), or it is * (tabindex=-1), or it is <button>, <textarea>, <a href> <input type=*>, etc).I think the logic behind Safari's choices around how a user may focus certain elements is something along the lines of:
<button>) are not keyboard focusable by default (but users may opt in) because for mixed-modality users filling out a form rapidly they are more likely to get in the way if included in the tab order (e.g. "more info" or "reset password" links when you mean to navigate to the submit button)tabindex=0, plus some other elements like <details>, <audio controls> and <video controls> are also always tab-focusable in Safari.I think that comes down to three classes for built-in "user focusable" elements:
tabindex=0, etc)_If_ we ruled out wanting to emulate non-editable form control behaviour**, that would come down to whether something is:
So that comes down to four categories:
*** about tabbableThat seems both simpler and more robust than using ARIA roles, in particular since we don't yet have parity between ARIA roles and HTML elements (there's no video role, for example).
* in my experience, having an element with tabindex=-1 be focused on click causes many more problems than it solves, so I'm explicitly ignoring that behaviour here
** it would be straightforward enough to just add a click listener with preventDefault(), for example
*** a UA could also use other signals, such as form participation, to decide whether this should be treated as "always focusable"
If we ruled out wanting to emulate non-editable form control behaviour
**, that would come down to whether something is:
That would not be an acceptable solution for us.
Safari does not include all form controls in the tab order by default. Only "keyboardable" controls like textarea, input type=text, select (both list box and pop-up menu forms) and so forth. button, input type=button, input type=checkbox and so forth are not in the tab order. This default set mostly matches macOS native convention. (Of course, tabIndex items are in the tab order too regardless of element type).
This is slightly complicated by the fact that there's two different settings that can change away from the default tab order:
I don't think anything is tab-focusable without being mouse-focusable in Safari in any of the three possible sets of tabbable things. I do not have the time for more detailed testing but I wanted to throw out this clarification.
@othermaciej Thanks for clarifying.
It seems like the main sticking point would be capturing the difference between the behaviour styles of non-keyboard form controls and links.
Do you think that if an author marked a custom element as "UA decides", that the UA could use the element's role, or any other data, as a signal to make that distinction?
Do you think that if an author marked a custom element as "UA decides", that the UA could use the element's role, or any other data, as a signal to make that distinction?
I thought we didn't want to make decisions about non-AT related behavior based on ARIA?
Like I stated previously, it's also a bit problematic to hard code exactly the set of behaviors Safari has because we need to design this to be forward compatible. If someone somewhere introduced a brand new platform with a new set of exotic rules about which element is mouse & keyboard focusable, and which elements can be focused via sequential navigation, then existing custom elements ideally should adopt to those new exotic rules to a reasonable degree without manual updates / rewrites.
it's also a bit problematic to hard code exactly the set of behaviors Safari has because we need to design this to be forward compatible.
I don't follow - I'm suggesting the opposite of that: the developer chooses only "always tabbable" or "UA decides", and then the UA decides based on any set of signals it feels is appropriate.
I thought we didn't want to make decisions about non-AT related behavior based on ARIA?
I wouldn't want to decide focusability wholesale (i.e. which of the four categories I laid out an element should fall into) based on ARIA; I think that it would be appropriate for a UA to use a custom element's internal role as a signal as to how it determines the focus behaviour of an element which has already been determined to be user-focusable.
it's also a bit problematic to hard code exactly the set of behaviors Safari has because we need to design this to be forward compatible.
I don't follow - I'm suggesting the opposite of that: the developer chooses only "always tabbable" or "UA decides", and then the UA decides based on any set of signals it feels is appropriate.
Alice's idea looks to work well. The current Safari behavior can be explained by difference of elements' default roles.
The only concern is that a future platform might introduce an exotic focus behavior for elements which can not be distinguished by ARIA roles. e.g.
<input type=date>, which has no specific ARIA role.<input type=reset>, of which role is button and there are other elements of which roles are button.Even if a custom element author wants a custom element to follow such focus behavior, it's unable to signal it with ARIA roles. UAs need to find other signals. The custom element would have the default focus behavior if there are no such signals.
@rniwa @othermaciej How does Darwin deal with developer-introduced controls and introducing new controls of its own? Is there a system in place or are applications expected to be updated?
What would your preferred approach be here? Above you mentioned four categories being too few as it would not give enough room for more drastic behavior changes. Should we have a value for each thing you can consider a control today and let user agents map those as they see fit? If yes, I think I agree with the potential weirdness of using ARIA's role for this, even if somewhat fitting, as it would be the first time we attach semantics to it. Having an equivalent API with effectively the same values isn't that great either, but perhaps we can have something that sets both at once or some such.
@annevk It might be that the three-way distinction between keyboardable controls, non-keyboardable controls, and totally unfocusable non-controls is sufficient (since these distinctions seems to be present in other browsers). We may not need to maintain the distinction between links and non-keyboardable controls for custom controls. i.e. never let custom controls be link-like in the specific way that makes a difference only in Safari.
(How focus works in AppKit and UIKit is kind of confusing. I'm asking folks who know more how this customization is normally done. From quick testing, it looks like other apps include native link-looking controls when full keyboard access is enabled, and we'll likely review this behavior in WebKit now that it's come to our attention anew.)
In my understanding, the consensus at TPAC 2019 was to introduce hight-level categories of elements, and we should avoid enums representing concrete behaviors such as "non-keyboardable" because of future platforms and macOS's "Full Keyboard Access" setting.
So, if we don't apply Alice's UA-decides idea, the options would be something like:
unfocusablegeneral -- click-focusable and sequentially-focusable; e.g. <div tabindex=0>, <input>control -- Safari: not-user-focusable or sequentially-focusable depending on "Full Keyboard Access" setting. Chrome: same as general.general.Code example:
this.internals_.focusBehavior = 'control';
@tkent-google: that seems about right to me, and aligns with @othermaciej's comments. I like the future-extensibility of unknown values being assumed as "general".
@annevk @othermaciej @rniwa @alice, is it ok to proceed with this API shape though we should brush up keywords?
It seems no one has concerns. Let's bikeshed on names.
ElementInternalsfocusBehavior, defaultFocusBehavior, focusCategory, defaultFocusCategory, or other ideas?
unfocusable, none, '' (empty string), or others?general, focusable, or others?control, non-editable-control, button, or others?non-editable-control might be confusing depending on the outcome of https://github.com/whatwg/html/issues/3501. And a checkbox (which is in the third category as I understand it) is not a button.
My pick: focusBehavior, unfocusable, focusable, focusable-non-editable. I'm not sure about the last one.
non-editable-control might be confusing depending on the outcome of whatwg/html#3501.
I think we can sidestep that because read-write/read-only are the terms used there, whereas here we're talking about using "editable", which is a (mostly) new word.
non-editable-control might be confusing depending on the outcome of whatwg/html#3501.
I think we can sidestep that because read-write/read-only are the terms used there, whereas here we're talking about using "editable", which is a (mostly) new word.
How about simple-control if there is a concern about "editable"?
<select> and text fields belong to the same group in Safari, and it's hard to assume <select> is "editable." So I also think "editable" should be avoided.
I'll start to make a specification pull-request.
I think "non-keyboardable" might be more clear than "non-editable". But that's still kind of weird since the other types of controls often do handle some keyboard input, even if it's only return or space. "simple-control" also seems good.
One point I am confused about: control was described in https://github.com/w3c/webcomponents/issues/762#issuecomment-557488222 as a Safari-specific distinction, but per https://github.com/w3c/webcomponents/issues/762#issuecomment-484461545 , it seems like Chrome would care about this distinction too, at least on macOS.
FWIW, Firefox cares about the distinction on macOS.
Regarding "editable", does that boil down to text-editable? If that is the case, could we combine this with the hinting we use for :focus-visible, which in practice is equivalent to "does this show a virtual keyboard if a physical keyboard is not present"? Could we have a primitive for _that_ concept (which is very close to inputmode), instead of making it a separate focus type?
@othermaciej
One point I am confused about:
controlwas described in #762 (comment) as a Safari-specific distinction, but per #762 (comment) , it seems like Chrome would care about this distinction too, at least on macOS.
My older comment was incorrect. Chrome doesn't respect "Full Keyboard Access" setting. crbug.com/119125
@alice
Regarding "editable", does that boil down to text-editable? If that is the case, could we combine this with the hinting we use for
:focus-visible, which in practice is equivalent to "does this show a virtual keyboard if a physical keyboard is not present"? Could we have a primitive for _that_ concept (which is very close toinputmode), instead of making it a separate focus type?
AFAIK, In Chrome the control category discussed here matches to elements which don't match to :focus-visible. So the specification may mention that the category might affect :focus-visible selector.
I'm not sure about relationship with the virtual keyboard stuff. Chrome and Safari don't show a virtual keyboard for focused <select>, but <select> is click-focusable, right?
Seeing https://github.com/whatwg/html/pull/5120 brings up an issue that "unfocusable" being the default is a bit strange. In particular, currently <x-element tabindex="0"> will be focusable. But then we have internals.focusBehavior === "unfocusable", so it is both focusable and unfocusable, which is confusing.
Given this, I think maybe focusBehavior = "none" is better than focusBehavior = "unfocusable". And we should probably explain that tabindex takes precedence over all of these? I'm not sure where that last part would fit in the spec, if it does.
The default case should probably be "default", "auto", or simply "".
The interaction with tabindex will have to be defined for all states, no?
In the PR, I changed unfocusable to default, and tried to explain tabindex= still works.
Just catching up a bit more:
@othermaciej
keyboardable controls, non-keyboardable controls, and totally unfocusable non-controls
What are non-keyboardable controls? What would their focus behaviour be?
And why does this list not include programmatically focusable elements (i.e. tabindex=-1, but without the annoying click behaviour)?
I realized (thanks @smaug----!) that simple-control goes against https://whatwg.org/style-guide#tone and is perhaps also not that clear.
Is there a reason we did not go with keyboardable-control, non-keyboardable-control, and non-control?
Is there a reason we did not go with keyboardable-control, non-keyboardable-control, and non-control?
Yes. The names keyboardable / non-keybordable are confusing on keyboard-less platforms. But it might be a minor issue.
Something like user-agent-decides from https://github.com/w3c/webcomponents/issues/762#issuecomment-542509589 would be another option.
So on iOS, with a virtual keyboard (or does that not count as a keyboard-less platform?), there are two arrow "buttons" that roughly correspond to tabbing and that appear to follow the same conventions from a rudimentary check.
I would also be okay with tabable and non-tabbable: https://en.wiktionary.org/wiki/tabbable. This also matches a bit with tabIndex as a bonus.
I think keyboardable and non-keyboardable are good. Nearly all platforms have either hardware or onscreen keyboards. On platforms that don't have a keyboard, what would focus even mean? (I guess you could have voice focus for a voice-only device, but this seems obscure.)
tabbable and non-tabbable aren't quite accurate. The distinction is about when something is tabbable (which could depend on browser or system settings), not whether it is tabbable at all under any circumstances.
keyboardable is about whether the control offers more than trivial keyboard interaction once focused, not about when focus happens, so it's better in this regard.
I'm concerned "keyboardable" will create confusion with things like buttons, which as @othermaciej points out earlier in the thread, offer some minimal keyboard interaction as a fallback. And what about something like a slider, which has relatively complex keyboard interaction, but probably wouldn't be considered "keyboardable"?
I think the critical concept (other than <select>, which IMO is an outlier) is whether you _primarily_ interact with something via the keyboard - i.e. whether you can type into it.
My thinking around tabbable was about the naming reflecting the default behavior, with the hope that it would make web developers also pick the correct default for their control. Users can override non-tabbable to be tabbable.
I cannot reach the first control in data:text/html,<input type=range><input> with a tab in Safari, though I can in Chrome/Firefox. And yeah, <select> can be reached.
If we want to go for naming after behavior, is the distinguishing factor text input perhaps (you can search a <select>), but cannot search a <input type=range>? (Although if you give a <input type=range> labels through <datalist> (not widely supported I think), is it really that much different?)
@othermaciej
I guess you could have voice focus for a voice-only device,
Yes, I supposed such devices which probably don't exist today.
@alice
I think the critical concept (other than <select>, which IMO is an outlier) is whether you primarily interact with something via the keyboard - i.e. whether you can type into it.
I agree that <select> is an outlier. I checked macOS native behavior, not Safari behavior, and found that NSPopupButton and widgets like listbox are not tabbable by default.
So, how about text-control (behavior like <textarea>) and control (behavior like <button>)? They don't match to the current Safari behavior perfectly, but it should be easy for developers to understand.
I agree that
<select>is an outlier. I checked macOS native behavior, not Safari behavior, and found thatNSPopupButtonand widgets like listbox are not tabbable by default.
That's correct about popups in macOS system UI. We made an exception for WebKit for complicated reasons (can explain if needed), and Safari/WebKit popup buttons allow typing (without even having to hit space to pop up the menu first). However, all the list boxes I could find in macOS system apps are in the tab focus cycle. They also allow typing - if you start typing the prefix of an item in the list it will select it.
Based on that, I don't think text-control is right, but maybe accepts-text-input? That's the distinction macOS (and Mac Safari) is trying to draw. Other things similar to list boxes (e.g. table/grid controls) should also accept tab focus by default.
Based on that, I don't think text-control is right, but maybe accepts-text-input? That's the distinction macOS (and Mac Safari) is trying to draw. Other things similar to list boxes (e.g. table/grid controls) should also accept tab focus by default.
I think if that's the critical concept, that it should be a concept in its own right: it also determines things like on-screen keyboard display and is an input into :focus-visible matching.
Which brings me back to my original proposal in https://github.com/w3c/webcomponents/issues/762#issuecomment-542509589 of four distinct categories:
<select>)Naming-wise, perhaps:
focusability
default
programmatic
auto
sequential
I don't understand why we need four categories. The previous proposals had three. Punting the "accepts text input" thing to a separate property should collapse two of them, leaving us with two instead of three. We'd have focusable and accepts-text-input booleans, where the combo of focusable being true and accepts-text-input being false would be invalid.
Compared to the two booleans, I think it's simpler to have a single tri-state: text-input-control, control, non-control. Or something.
It seems like you are suggesting that neither the two booleans nor the tri-state adequately cover the possibilities, but I don't understand what is missing. I guess "programmatically focusable" but please make the case for that separately. Seems like that got lost from the conversation after your comment.
The previous proposals dropped programmatically focusable, as you pointed out: hence three rather than four (default, keyboardable, non-keyboardable, or some variation thereof).
I make the split between keyboardable and non-keyboardable slightly differently:
sequential is close to keyboardable, but just says "trust me and always put this in the tab order" (i.e. <select> and other special cases - identical in behaviour to tabindex=0)auto is kind of a conflation of the two non-default options, where it is up to the UA to determine whether it wants to include something in the tab order or not, presumably based on accepts-text-input or whatever other heuristics make sense in context.accepts-text-input would also presumably opt an element into other things like showing an on-screen keyboard when focused and always matching :focus-visible when focused, which is why I think it's a separate concept. Certainly splitting it out makes naming clearer, per my proposal in the previous comment.
I guess it boils down to whether we want people to be able to create their own text-editable elements (via listening for keyboard events on an otherwise ordinary element), or require everything to either use contenteditable or be an existing text-editable element (in which case we don't need a "text-editable" concept since we'll be able to tell based on that restriction which elements are text editable).
please make the case for [programmatically focusable] separately.
Complex widgets, such as tab panels, list boxes menus, tree views, grids etc. will typically have many interactive parts, but only represent one "stop" in the sequential focus (tab) order.
This is achieved in practice by programmatically moving focus to interactive elements within the widget, often "roving" which sub-element should take part in the tab order.
For example, an <x-tree> pattern might have a number of <x-node> elements, but only the one the user last interacted with would be in the sequential focus order. The remainder would be programmatic focusable, becoming auto or sequential focusable depending on user interactions.
Having four options plus an extra boolean seems more complicated than having four options (if we need to add back programmatic; likewise for 3+boolean vs 3 if we don't). And the auto vs sequential distinction seems hard to understand from the names and descriptions. Seems like it will lead to lots of authors carelessly choosing sequential, since authors won't know what "up to the UA" will actually do, and thus custom controls won't actually play nice with platform conventions.
I think we do want to allow people to be able to create their own elements that accept text input. Note that, much like list boxes or pop-ups on the Mac, these may not actually be text editable. One obvious example would be a non-editable multicolumn list views that supports typeahead.
Complex widgets, such as tab panels, list boxes menus, tree views, grids etc. will typically have many interactive parts, but only represent one "stop" in the sequential focus (tab) order.
On macOS, with full keyboard access enabled, in many cases, each such interactive part should be in the tab order. Without full keyboard access, it shouldn't be. At the very least, that's true for tabs and tree views. List boxes don't give individual focus to their elements, the list box as a whole is the only thing to get focus. Likewise for menus. For grids, I'm assuming you mean editable grids, like a spreadsheet, and those tab to each item.
Maybe on other platforms this category makes more sense, but on macOS any use of it for the named items would violate platform conventions. Whereas using either control or text-input-control categories (depending on whether the piece takes text input) or none if non-control the container is supposed to get focus would do the right thing.
This is achieved in practice by programmatically moving focus to interactive elements within the widget, often "roving" which sub-element should take part in the tab order.
Are parts like that not meant to be click-focusable? What exactly sends programmatic focus to a specific piece?
I think the complexity reflects the actual situation, rather than being unnecessary. The existing API, tabindex, is overly simplistic in ways that cause problems for authors.
For example, <input type=text disabled> could be considered focusability: default (although adding a tabindex does nothing so it's kind of yet another state) and accepts-text-input: true.
In terms of having authors choose between auto and sequential, it's true that some education will be required that auto is likely the right option in most cases.
I think we do want to allow people to be able to create their own elements that accept text input. Note that, much like list boxes or pop-ups on the Mac, these may not actually be text editable.
To flip this logic: for the elements which _are_ text editable, how would they opt in to displaying an on-screen keyboard, without using contenteditable or one of the existing text input elements?
If there was a way to do that, should it not opt the element into the sequential focus order automatically?
For the elements which _aren't_ text editable, should they show an on-screen keyboard?
One obvious example would be a non-editable multicolumn list views that supports typeahead.
Could you expand on that example? I can't picture it from the brief description, sorry.
On macOS, with full keyboard access enabled, in many cases, each such interactive part should be in the tab order. Without full keyboard access, it shouldn't be. At the very least, that's true for tabs and tree views.
I just tested it on the macOS settings app, and tabs are one tab stop in that context. Arrow keys choose between the different tabs (and move the focus indicator).

I couldn't find a tree view to test with - the files list in Finder seems to put things in a totally random tab order.
List boxes don't give individual focus to their elements, the list box as a whole is the only thing to get focus. Likewise for menus.
Conceptually this is true, but authors often implement that concept on the web by focusing individual elements, for a variety of reasons. This is the reason tabindex=-1 was originally added to the platform.
For grids, I'm assuming you mean editable grids, like a spreadsheet, and those tab to each item.
It may also be a layout grid, like the Google Docs recent documents list:

In that case the entire grid is one tab stop, with arrow keys allowing movement between items. This is to prevent the grid being a de-facto "tab trap" if keyboard-only users need to navigate to content before or after.
Are parts like that not meant to be click-focusable? What exactly sends programmatic focus to a specific piece?
It would be an event listener for either a keyboard (arrow key) event on an adjacent item, or a pointer event.
It's a valid question whether programmatic focusable elements should be click-focusable or not. I've tended to think they shouldn't, since click focusability has caused confusion when tabindex=-1 has been used to make container elements programmatically focusable but non-interactive elements to simulate moving the focus navigation start point (such that the user clicks, say, a paragraph of text and a focus outline shows up), but perhaps https://github.com/whatwg/html/issues/5326 is a sufficient solution to that problem.
On macOS, with full keyboard access enabled, in many cases, each such interactive part should be in the tab order. Without full keyboard access, it shouldn't be. At the very least, that's true for tabs and tree views.
I just tested it on the macOS settings app, and tabs are one tab stop in that context. Arrow keys choose between the different tabs (and move the focus indicator).
I think you have this checkbox turned on, which is off by default. This is what "full keyboard access" Maciej was talking about in his reply:

The disconnect is that when I referred to tabs I meant window-level tabs, like this:

For tabs like that, each is always in the tab focus order.
What Alice screenshotted is a "segmented control" but may also reasonable be called tabs.
I can confirm that it has the behavior she describes; it's a single stop in the tab order, it draws a focus ring around exactly one item, and it moves through the items with arrow keys. A similar thing is true of radio button groups in native UI; only the currently active radio button is in the tab order. Or, looked at another way, a radio button isn't a control, a radio button group is. Indeed, the segmented control is sort of an alternate presentation of a radio button group. WebKit even replicates this behavior of radio button groups in HTML when "Use keyboard navigation to move focus between controls" is enabled.
I'm not sure this pattern is best represented. Under full keyboard access, radio buttons are individual elements that are always click-focusable, but, at least on macOS (not sure how this works on Windows), only the active one is in the tab cycle. It's reasonable for other elements intended to be part of a group to have this behavior. Less clear (to me) whether there is a need to not be click focusable in such a scenario.
What Alice screenshotted is a "segmented control" but may also reasonable be called tabs.
I can confirm that it has the behavior she describes; it's a single stop in the tab order, it draws a focus ring around exactly one item, and it moves through the items with arrow keys. A similar thing is true of radio button groups in native UI
I'm pretty certain that behavior only exists if "Use keyboard navigation to move focus between controls" in (somewhat misleadingly labeled) Shortcut section of Keyboard in System Preferences is checked (I've confirmed this on 10.15.3 19D76). By default, you can't press tab key to focus any section title in Keyboard or any of the checkboxes.
@othermaciej wrote:
List boxes don't give individual focus to their elements, the list box as a whole is the only thing to get focus.
@alice replied
I just tested it on the macOS settings app, and tabs are one tab stop in that context. Arrow keys choose between the different tabs (and move the focus indicator).
If I understand the distinctions you're each making, you two are agreement on the relevant parts.
Maciej mentioned that managed focus AppKit controls don't focus the sub-views, per se. But AppKit does style the sub-views and vends enough information for AT to understand the relationship... Somewhat similar to the concept of aria-activedescendant
Alice mentioned that more web controls use the other managed focus technique: roving/roaming tabindex. (There's a demo video of r–ing tabindex in Example 2 of this 2014 WebKit post). Each technique is useful.
In both cases, on Web or native platforms, the user experiences the same end result: one tab stop, with other non-Tab keypresses modifying the widget's sub-level focus or visible focus indicator. The distinction of whether the container or the sub-view gets actual focus feels like a implementation detail of the platform.
Aside: should elements with @draggable get a default focus behavior, too?
Attributes that affect focusability (or should):
tabindexhrefdisabledcontenteditabledraggable?Feel free to edit this comment to add any I overlooked.
I'm not sure what the latest is in this thread and proposal, but I'll drop a note that the eventual proposal should be sure to make the resulting controls interactive content. As https://github.com/whatwg/html/issues/5414 points out this has an effect on <label> behavior.
Perhaps autofocus should also be considered within this issue, to take into account the case when FACE is upgraded?
I think they might be orthogonal, but someone else may be able to correct me - i.e. autofocus may be used on any element, and if the element is not a focusable area at the time the "flush autofocus candidates" algorithm is run, and "getting the focusable area" returns no result, the element simply isn't focused.
Right, but it means that when the new way to make an element focused, is provided according to this discussion, it will not work with autofocus (or even worth, it will provide intermittent results).
It seems reasonable to update autofocus spec so that the algorithm is also triggered when custom element is upgraded.
I see - on document load, the element may not yet be focusable, since it hasn't yet upgraded.
I've also stumbled upon on "always tab-focusable audio controls in Chrome regardless of tabindex". Had to do a JS workaround :( For some fast tab-navigation scenarios 6 audio controls being tabbed-through destroys the tab navigation usecase, especially when audio isn't supposed to be played often and tab navigation is supposed to be used often (in some crowd-sourcing scenarios)
From this gist, @alice wrote:
I think we can get away with two states, with several caveats.
The states would be:
focusable(orauto, or...)
default(orunfocusable, or...)The caveats:
unfocusablecustom elements would still be programmatically focusable.
So, custom elements set as unfocusable would not be in the tab order, but would still achieve focus if the author called the .focus() method on the custom element. Correct?
Safari would need to determine click/sequential focusability of focusable elements based on ElementInternals role.
Another gist gives an example of using these two states to manage focus within a complex custom element.
Safari would need to determine click/sequential focusability of focusable elements based on ElementInternals role.
"Safari would need to" may not be true. I see at least two options:
Safari _could_ (No opinion yet on whether it should) use the focusable state plus role as a way to determine whether elements appeared by default in the tab order, based on the existing platform keyboard behavior as modified by system and browser settings.
firstResponder) that achieving focus (even programmatic-only) would be incompatible with the unfocusable state. I'll let him explain that concern in further detail.<button> but it's always been so. We'd be adding a _new_ interop problem here.For custom elements, Safari could treat them like it does ARIA elements (E.g. <div role="button" tabindex="0">), where focusability and tab order is controlled by the focusable/unfocusable state (role ignored), and programmatic .focus() calls would be ignored on non-focusable elements.
@Alice wrote:
unfocusablecustom elements would still be programmatically focusable.
Above you mentioned roaming/roving tabindex as the primary justification for programmatic focus, but most of the examples I've seen toggle the state of those sub-controls between tabindex="0" and tabindex="-1" effectively making them focusable and non-focusable. The portion of the control gets focused is always made focusable at the same time the author calls .focus(), right?
If so, maybe it's okay to force the author to make a custom element focusable before calling .focus()... Putting this limitation on custom elements may bring us back to a simpler boolean state: focusable or not.
In chrome://settings/appearance, there is a setting that is similar to the Mac Safari setting, called: "Pressing Tab on a webpage highlights links, as well as form fields." @Alice, would your proposal to have Safari adjust tab-focus by role also apply to Chrome in this context?

From this gist, @alice wrote:
I think we can get away with two states, with several caveats.
The states would be:
focusable(orauto, or...)
default(orunfocusable, or...)
The caveats:
unfocusablecustom elements would still be programmatically focusable.So, custom elements set as
unfocusablewould not be in the tab order, but would still achieve focus if the author called the.focus()method on the custom element. Correct?
Making custom elements always programmatically focusable doesn't seem like a backwards compatible change to me. During our work to make Safari to iPad load desktop sites, we encountered numerous websites including Microsoft Office 365 that move focus inadvertently(?) to multiple elements before the correct element is focused. Making previously non-programatically focusable element always programmatically focusable has a risk that it would make previously no-op focus() call move the focus to the context object and blur the previously focused element. This can result in a wrong element having the focus. We need to come up with some way to mitigate this backwards compatibility risk. I don't that's the kind of compatibility risk we want to take given how many tricky-to-diagnose bugs we've encountered in this area especially in conjunction with iOS's software keyboard & focus scrolling behavior.
Here's my attempt of summarizing the discussions we've had so far.
In 2018 TPAC, we concluded that we wanted to respect platform differences. One approach considered is adding the ability to match other element's behavior. One of the simplest approach propsoed by tkent-google is to add a signle boolean like defaultTabindexFocusFlag in ElementIntenals. Domenic's counter propsal is that we may need tri-state to capture click vs. keyboard focusability. I pointed out that Safari differentiates editable and non-editable form contorls as well as hyper links so we may need four different states along with a point that listing exactly what Safari needs won't be future proof.
In 2019 TPAC, we discussed the idea of using ARIA role as a way of detecting which element is focusable. Alice proposed that if we ignored non-editable form control behavior, we can narrow the cateogires down to four: unfocusable, programatically focusable, user focusable but keyboard focusable depending on UA, and always keyboard focusable. Maciej then pointed out that Safari doesn't include all form controls in the tab order; only editable ones like textarea is included. Tkent then brings up that at 2019 TPAC, we came to a conseusus to introduce a high level categories and sgugests: unfocusable, general, and control. There was some bikeshedding.
After more bikeshedding, Alice suggested that we can have four categories: unfocusable, programmatically focusable, user focusable but UA dependent for tab order, and user focusable and always in tab order. Maciej points out that if we split "accepts text input" (i.e. editability) into its own property, then we need two states but suggested that tri-state is simpler: text-input-control, control, non-control. Alice then suggests that we can have "sequential" and "auto" instead where the former means always in tab-order and the latter means UA decides. In Maciej also questioned why we need programatic focusability separately and Alice replies that some complex widgets would need this capability to control which sub-components would need focusing. Maciej mentions that leaving UA to decide what is in tab order will result in developers writing components that don't play nicely with platform conventions. Then there are some macOS specific UI discussions.
More recently, Domenic pointed out that this propopsal needs to also make the focusable custom element interactive content as it affects label element's behavior. Then Alex pointed out that we may also need to trigger autofocus once custom elements are upgraded.
@alice, would your proposal to have Safari adjust tab-focus by role also apply to Chrome in this context?
Wow, TIL.
Yes, I agree Chrome should be consistent with whatever Safari decides (i.e. treating Custom Elements the same for focus as either <div tabindex=0>, or treating them the same as built-in elements with the same role).
maybe it's okay to force the author to make a custom element
focusablebefore calling.focus()... Putting this limitation on custom elements may bring us back to a simpler boolean state:focusableor not.
This is definitely worth experimenting with; it would avoid the issues @rniwa mentioned.
I had a play with doing this with tabindex: https://codepen.io/sundress/full/oNxqYaR
I do seem to recall that there were some potential issues with this, but so far I can't remember what they may have been.
I asked a colleague who works in front-end development, and they noted that not having a programmatic focus state means there is extra (and thus potentially error-prone) work when you want to move focus to something but not have it remain user-focusable after focus moves away. Maybe the solution there is an option to focus() to override the focusability bit?
@Alice wrote:
I asked a colleague who works in front-end development, and they noted that not having a programmatic focus state means there is extra (and thus potentially error-prone) work when you want to move focus to something but not have it remain user-focusable after focus moves away. Maybe the solution there is an option to focus() to override the focusability bit?
How would that be different than making all custom elements always programmatically focusable? Wouldn't it result in the same problems @rniwa mentioned on the Microsoft Office 365 web app?
How would that be different than making all custom elements always programmatically focusable?
I meant to suggest that you would have to opt-in to overriding the focusability bit, e.g. focus({force: true});
If you're depending on focus() being a no-op for non-focusable elements, you wouldn't use that option. Also, it wouldn't cause existing code to suddenly change behaviour.
While we're exploring options, we should keep our use cases in mind as well. I can really only think of two use cases for tabindex=-1 behaviour:
Are there any other use cases I've missed?
We discussed this at this week's web component meeting.
@rniwa put forth an update to Apple's tri-state proposal referenced in his summary above. In this, elementInternals would have a focusMode property with three values:
The difference between #2 and #3 would let Safari provide its distinct UI behavior in which focus skips components in category #3 by default.
Various people expressed questions about how developers would distinguish between categories #2 and #3, particularly for new types of components that have no analogues among the existing HTML elements. E.g., one class of interesting components are list boxes and other elements that support typeahead (type some characters to select an item that begins with those characters). Do those components edit text?
Given that Apple is the entity making the distinction, the suggestion was that Apple provide guidelines about how it would categorize various categories of elements whose focusability might conceivably be in question. Those guidelines could then be incorporated into the documentation of the focusMode enum so that developers could make a reasonable determination on their own as to which value best reflected the component's use.
One concern raised with this proposal is that, by default, WebKit does not focus components in category #2 — e.g., form controls like radio buttons — when the user clicks on them. That behavior might confuse or cause problems for a web developer using that #2 focusMode value for their component.
FWIW I continue to be excited about tri-state proposals that let custom elements continue to capture the same capabilities as built-in elements. And I am glad that this is orthogonal to other pieces of state (e.g., role). I am willing to help with updating @tkent-google's tri-state pull request (https://github.com/whatwg/html/pull/5120) with appropriate new names and documentation, once folks have figured them out.
I'd like to continue the discussion about programmatic focus, just to make sure we aren't missing any critical functionality by excluding it.
I'd be interested to hear from @JanMiksovsky or any other web component developers whether the use cases I listed in https://github.com/w3c/webcomponents/issues/762#issuecomment-692416176 are the full range of what tabindex=-1 is used for in practice.
For (1) above, perhaps a worked example might help with intuition.
Say you're developing a date picker widget. When the date grid dialog is open, you'd want to be able to programmatically move focus/selection among the days of the month shown, but only have the pre-selected month appear in the focus order.

In this screenshot, the user had previously used the arrow keys to move focus/pre-selection to "1", and then used the tab key to move focus to the "previous month" button.
If the user uses the tab key to move the focus back to the calendar grid, the "1" cell will be focused again. If the user clicks on any of the other days, or uses the arrow keys to select an adjacent day, that day will be focused and pre-selected (the selection not being committed until the user activates the 'Ok' button).
I am interested in whether developers would tend to:
tabindex to make the day elements programmatically/sequentially focusable as necessary, or ElementInternals, orElementInternals, so that you could call focus() without having to have access to the ElementInternals or use tabindex to make the element focusable first.
Most helpful comment
In all honesty, I've never understood why
tabindex = -1is a thing, other than for excluding things from the tab order - i.e. why aren't all elements programmatically focusable? What do we gain fromfocus()sometimes being a no-op? Who is out here trying to callfocus()on a<div>and hoping it ... fails?But that aside, I guess allowing focusable things to also opt out of the tab order is probably useful for managing focus within complex components.