-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Focus meta-bug #4607
Comments
One thing to follow up with: I am generally not proposing many, if any, changes to browser behavior. The majority of this issue is about aligning the spec with reality. The intent is to preserve browsers' flexibilities in terms of focusing behavior, while also documenting it accurately in the spec. Concretely, I expect the only changes browser implementers will make will be:
|
One aspect I do not see mentioned is focus rings, as discussed at #938 (comment). |
Focus rings seem covered fairly well by the CSSWG. https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo |
I wanted to add that I am hugely supportive of a big effort to as much as possible help explain/unwind focus and add something that developers can hope to understand and get right. I too have had so many conversations over the years on these topics. Another common frustration that I don't see specifcally logged here specifically (but might be covered by something you wrote?) is that we kind of overload the purpose of focus because it's all we have and this gets sort of confusing. Developers, for example, learning about keyboard accessibility initially tend to want to make all the things focusable, which is almost worse. So, we try to develop simple rules like "only interactive elements should be focusable" or "interactive elements shouldn't contain interactive elements", but these rules break down very quickly and wind up actively confusing people because, for example, many patterns require them. Skip links or in page anchors, for example, really want part of that - basically, they want to scroll/shift attention and where the search for the next sequentially focusable element (focus navigation starting point) begins, but not actually imply that this is an interactive element or something. Similarly, as you mentioned 'widgets' often manage a kind of manage what is effectively a 'secondary' focus. In some ways, shadow dom at least gives a concept here for that, but all ARIA patterns currently have to deal with all of that, traditionally in the light dom and I have both experienced and heard so much confusion around this. Managing where focus 'returns to' in all of these is frequently a very frustrating thing to try to manage as well. |
@domenic how does "the user agent determines via heuristics that the focus should be made evident on the element" work for custom elements? At least reading the suggestions in that document it seems that might very much depend on particular details of the element. |
Fair point. I guess that is further support for the "pick a native element to emulate" style of behavior. |
You may also want to look at the related FocusTraversalAPI proposal I submitted to the WICG a few months ago. I would love a whole lot more input on it and it desperately needs a major signal and visibility boost. Explainer: https://github.com/awesomeeng/FocusTraversalAPI/blob/master/EXPLAINER.md Proposal and discussion: https://discourse.wicg.io/t/proposal-focus-traversal-api/3427 |
There appear to be some encoded characters in the hrefs there causing them to not work but the displayed urls seem right |
@bkardell fixed the links. Thanks. |
Seeing this I realized I had not considered the case of But of course this will still fail on option on macOS. |
Yeah, the option on Safari-macOS issue, or any future innovations in focusablity, make exposing new things like sequential focusability a bit troublesome. (And in particular, putting myself in the Safari team's shoes, I'm not sure I'd want to add it to the platform.)
In particular this only matches macOS Safari with option held down. I.e., this will return true for things like checkboxes or buttons which are not sequentially focusable there in the default state. |
@muan @domenic many of the common utilities around focus distinguish between focusable and tabbable, and ARIA plays into that as well. What I wrote in the FocusTraversal API (see previous posts) was to expose a means to determine what is focusable or not. It might serve to also expose the other characteristics around focus as well, eg what is tababble, what is autofocusable, etc. |
Is there a specific issue filed for |
Nothing filed yet, as the spec isn't really clear on any of this. But I'll take the above as a sign that you'd appreciate an issue filed, even in the absence of a clear spec to support it :). Bugs: |
@tkent-google discovered that my test case for I have closed the above two browser bugs as invalid, updated the test page to have "click me" programatically focus an |
This updates the tabIndex getter's default value to be 0 for a specific list of element types, instead of the spec's previous "elements that are focusable". This matches reality better; apart from minor edge cases all three browser engines match this spec in observable behavior. Closes #1786. Closes #4464. See the focus meta-bug in #4607 for related discussions, including on adding an API that actually reflects whether an element is focusable (like the tabIndex getter was kind-of supposed to do). Tests: web-platform-tests/wpt#17657
This is a great overview, thanks @domenic. Very complicated problem space to start tackling (and thus very rewarding, right, right?). This is an area that I know @melanierichards and @atanassov are also looking to participate in, so CC-ing them so they can start following too. |
Dumping this here for reference. Here is what you can control about focusability of elements today:
Contrast this with the "most primitive" model, which would give you something like:
|
Define "focusable" more concretely, and as part of it, define special types of focusability: click focusable and sequentially focusable. As part of this, remove the "tabindex focus flag" because it can be replaced with "focusable" and "focusable area", and was very confusing. Part of #4607. Helps provide a basis for further work on #2013, but does not directly contribute to any shadow DOM upstreaming. This does not introduce any normative changes, but instead brings into the spec behavior that was previously only in implementations, and makes certain concepts explicit.
Some more stuff to consider about focus that I don't see mentioned above:
|
Define "focusable" more concretely, and as part of it, define special types of focusability: click focusable and sequentially focusable. As part of this, remove the "tabindex focus flag" because it can be replaced with "focusable" and "focusable area", and was very confusing. Part of #4607. Helps provide a basis for further work on #2013, but does not directly contribute to any shadow DOM upstreaming. This does not introduce any normative changes, but instead brings into the spec behavior that was previously only in implementations, and makes certain concepts explicit.
Hello. I wonder the progress of 'Simplify focusable areas concept in the spec' as one of the action item here. According to the current spec, the scrollable element is one of the focusable areas, but it works differently between browsers. If Chrome can enable KeyboardFocusableScrollers option by default, it follows the spec and other browser, but it hasn't yet due to some issues. Please refer the following discussion and example on why Chrome hasn't made the scrollable element to be a focusable by default yet. |
Hi @anawhj. The spec allows browsers to determine whether something is a focusable area or not, so it's up to Chrome whether they want to make scrollable elements focusable by default or no. The "Simplify focusable areas concept in the spec" action item isn't really related to this question; it's more about a spec refactoring. |
Hi @domenic. Thank you for the clear explanation! I thought the focusable area described at the spec as a table form would be the normative requirement so that we could prevent any fragmentation between browsers but it seems not. I was just confused that the spec says the examples in the table are non-normative but the 6.5.2 section itself doesn't describe 'this section is non-normative' as the 6.5.1 section does, though. I just wanted to get your experienced opinion on the issue I've mentioned above. :) |
Motivated by WICG/webcomponents#762 and #2013, I've realized we need to fix the shaky spec foundations for focus. I've spent the last couple of days canvasing the open issues and trying to come up with a path forward. Here are my results.
Pinging @rniwa, @cdumez, @muan, @tkent-google, @alice, and @bzbarsky as folks who have been involved previously. Feel free to skim/unsubscribe if you're not as interested.
Types of focusability
Previously discussed in #938 and #1786.
There appear to be three types of focusability:
.focus()
,autofocus=""
)Only the first one is script-observable or testable. The others are based on user interaction. But I think the spec should talk about them, as they are important parts of building a browser, and various things the author controls, such as
tabindex=""
can impact them (at least at a "should" level). Note that the spec already talks about sequential focus navigation.A lot of different combinations can occur here. Here are some examples showing all combinations I've seen so far. (All use default OS settings.)
<span>
<input type="text">
<span tabindex="-1">
<div>
with overflowing contents<area>
(withhref=""
)<area>
(nohref=""
)<area>
(either case)<input type="checkbox">
<input type="checkbox">
UAs generally vary wildly on whether something is sequentially or click focusable. This test page (derived from @muan's earlier work) is a playground where you can find out for yourself.
How does this related to today's spec?
Today's spec captures something like this, but in a way that I found hard to understand.
I think the tabindex focus flag is especially confusing because sometimes it's set according to UA convention, sometimes it's set with a "must", and it always only has a "should" effect on sequential focus order. It's not clear what's up to the UA and what's required by the spec.
Also, the name "tabindex focus flag" is very uninformative.
Path forward
I think we should overhaul the spec's model to follow the above.
I think ideally we could have the invariant that something is only sequentially/click focusable if it is programmatically focusable. All browsers seem to follow this.
I think that, like the current spec, we can state that some things are never focusable, and continue to offer examples or guidance on what kind of things authors expect to be focusable, in what ways. But I don't think we can mandate anything besides that certain controls are never focusable.
The only thing I'm unsure about is whether "sequentially focusable" should be a property of a focusable area, or if there should be a "get next sequentially focusable area" algorithm. The latter seems like it's a bit more flexible; for example it feels weird to say that a control's sequential focusability changes on macOS depending on whether the Option key is held down. But having "sequentially focusable" as a first class concept seems much easier to understand, instead of inlining the logic into the "get next" algorithm.
Writing tests for this will not be very possible, given the amount of UA leeway to change the user experience here. We can test the programmatically focusable requirements, but not much else. And I suspect those are already tested reasonably well.
Exposing these to web components (WICG/webcomponents#762)
I think @rniwa is right, in WICG/webcomponents#762 (comment), that it is not going to work well to expose these primitives directly to web component authors. For example, an API that let you separately configure programmatically focusable, sequentially focusable, and click focusable, is not going to age well as we evolve user interaction paradigms, and will not make it easy for authors to integrate with the platform.
I think the spec should still explain the current landscape and implementation models, but in a way that still allows innovation, probably through liberal use of "may" and "should". I am confident we can do that, ending up with a result that is similar but less fictitious. And, as long as we don't expose an API that paints us into a corner, we can always fix the spec if we accidentally made it too strict.
I am currently leaning toward something that lets you state what built-in control you want to emulate, perhaps from a restricted list. We can continue that discussion in WICG/webcomponents#762.
tabIndex
getter is mostly interoperable, but uselessThis was the main subject of #4464; it was also touched on in #938 and #1786. The test page shows that most browsers give the same results for
tabIndex
. However, it is almost entirely uncorrelated with a control's focusability. So for developers, such as @muan in #4464 or many others I've heard from over the years, who want to tell whether a control is focusable, it is not helpful.Path forward
I suggest we write down an interoperable spec for the
tabIndex
getter, based on what browsers do, and declare it useless for extracting focusability information.We should then introduce a new getter, something like
el.programmaticallyFocusable
orel.canBeFocused
, which gives whether a control is programmatically focusable. This does not expose any new information that could not be gotten today by creating the element, calling.focus()
, and seeing ifdocument.activeElement
changed. This would help meet the desire of #4464, and e.g. would allow web developers to re-implement their own version ofautofocus=""
(extensible web manifesto).I would like to introduce getters for whether a control is click focusable or sequentially focusable. However, I am unsure about baking in this kind of until-now-unobservable user interaction information, or how it would work with novel situations like macOS Safari's Option key business. I cannot see any way developers could usefully code against all browsers and still capture idiosyncracies like that:
So I think we'll have to leave that out for now
Other spec issues
Clarity: focusable areas
The spec's use of "focusable area", instead of working off of nodes, is confusing. There are three reasons why they are not 1:1:
Document
itself having focus, and then maps theDocument
itself having focus to the<body>
element being the activeElement. I am optimistic we could remove all this abstraction and just talk about the<body>
element itself.I'd like to simplifying this mapping significantly. I'm unsure whether we can completely get rid of the "focusable areas" concept given the sub-widgets issue, though. The best idea I have so far is to say that sub-widgets are handled by clauses like:
Both of these are only at the user interaction level. From the web developer's point of view, sub-widgets are invisible.
Work to do: autofocus=""
autofocus=""
on all elements.Work to do: upstreaming shadow DOM work
#2013 tracks this. This section provides an overview of the desired behavior, and this section seems to attempt to implement most of it, but not in a way that's super well-integrated. (For example, it seems like the focus chain needs modification to account for shadow roots/delegatesFocus.)
@tkent-google and I will try to work on this. I don't yet understand how much this might overlap with the above.
Appendix: roughly-ordered task list
autofocus=""
to all elementstabIndex
getter definition (make it interoperable but not useful)canBeFocused
useful replacement fortabIndex
getterThe text was updated successfully, but these errors were encountered: