:focus-visible in WebKit - February 2021
One month has passed since the previous report so it’s time for a status update.
As you probably already know, Igalia is working on the implementation of :focus-visible
in WebKit, a project that is being sponsored by many people and organizations through the Open Prioriziatation campaing. We’ve reached 84% of the goal, thanks you all! 🎉 And if you haven’t contributed yet, you’re still in time to do it if you believe this work is important for you.
The main highlight for February is that initial work has started to land in WebKit, though some important bits are still under review.
Spec issues #
There were some open discussions on the spec side regarding different topics, let’s review here the status of them:
-
:focus-visible
on<select>
element: After some discussion on the CSS Working Group (CSSWG) issue it was agreed to remove the<select>
element from the tests and each browser could decide whether to match:focus-visible
when it’s clicked, as there was not a clear agreement regarding how to interpret if it allows or not keybaord input.In any case Chromium has still a bug on elements that have a popup (like a
<select>
). When you click them they match:focus-visible
, but they don’t show the focus indicator (because they want to avoid showing two focus indicators, one on the<select>
and another one on the<option>
). As it’s not showing a focus indicator, it shouldn’t match:focus-visible
in that situation actually. -
:focus-visible
on script focus: The spec is not totally clear about when an element should match (or not):focus-visible
after script focus. There has been a nice proposal from Alice Boxhall and Brian Kardell on the CSSWG issue, but when we discussed this in the CSSWG it was decided that was not the proper forum for these discussions. This was because the CSSWG has defined that:focus-visible
should match when the browser shows a focus indicator to the user, but it doesn’t care when it’s actually showed or not. That definition is very clear, and despite that each browser shows the focus indicator (or not) in different situations, the definition is still correct.Currently the list of heuristics on the spec are not normative, they’re just hints to the browsers about when to match
:focus-visible
(when to show a focus indicator). But I believe it’d be really nice to have interoperability here, so the people using this feature won’t find weird problems here and there. So the suggestion from the CSSWG was to discuss this in the HTML spec directly, proposing there a set of rules about when a browser should show a focus indicator to the user, those rules would be the current heuristics on the:focus-visible
spec with some slight modifications to cover the corner cases that have been discussed. Hopefully we can reach an agreement between the different parties, and manage to define this properly on the HTML spec, so all the implementations can be interoperable on this regard.I believe we need to dig deeper in the specific case of script focus, as I’m not totally sure how some scenarios (e.g.
blur()
beforefocus()
and things like that) should work. For that reason I worked on a set of tests trying to clarify the different situations when the browser should show or not a focus indicator. These need to be discussed with more people to see if we can reach an agreement and prepare some spec text for HTML. -
:focus-visible
and Shadow DOM: Another topic already explained in the previous report. My proposal to the CSSWG was to avoid matching:focus-visible
on theShadowRoot
when some element in the Shadow Tree has the focus, in order to avoid having two focus indicators.There has been raised a concern, as this would allow to guess if an element is or not a
ShadowRoot
by focusing it via script and then checking if it matches or not:focus-visible
(butShadowRoot
elements shouldn’t be observable). However that’s already possible in WebKit that currently uses:-webkit-direct-focus
in the default User Agent style sheet, to avoid the double focus indicator in this case. In WebKit you can focus via script an element and check if it has or not anoutline
to determine if it’s aShadowRoot
.Anyway like in the previous case, this would be part of the heuristics so according to CSSWG’s suggestion, this should be discussed on the HTML spec directly.
Default User Agent style sheet #
Early this month I landed a patch to start using :focus-visible
in Chromium User Agent style sheet, this is included in version 90. 🚀 This means that from that version on you won’t see an outline when you click on a <div tabindex="0">
, only when you focus it with the keyboard. Also the hack :focus:not(:focus-visible)
won’t be needed anymore (actually it has been removed from the spec too).
In addition, Firefox is also using :focus-visible
on their User Agent style sheet since version 87.
More about tests #
During this month there has been still some extra work on the tests. While I was implementing things on WebKit I realized about some minor issues in the tests that have been fixed along the way.
I also found out some limitations of WebKit with regard to testdriver.js
support for simulating keyboard inputs. Some of the :focus-visible
tests use the method test_driver.send_keys()
to send keys like Control
or Enter
. I added support for them on WebKit. Apart from that, I fixed how modifier keys are identified in WebKitGTK and WPE, as they were not following other browsers exactly (e.g. event.ctrlKey
was not set on keydown
event, only on keyup
).
WebKit implementation #
And the most important part, the actual WebKit implementation has been moving forward during this month. I managed to have a patch that passed all the tests, and split it a little bit in order to merge things upstream.
The first patch that just do the parsing of the new pseudo-class and adds a experimental flag has already landed.
Now a second patch is under review. It originally contained the whole implementation that passes all the tests, but due to some discussion on the script focus issues, that part has been removed. Anyway the review is ongoing and hopefully it’ll land soon and you could start testing it in the WebKit nightlies.
Some numbers #
Like in the previous post, let’s again review the numbers of what has been done during in this project:
- 20 PRs merged in WPT (7 in February).
- 14 patches landed in WebKit (9 in February).
- 7 patches landed in Chromium (3 in February).
- 1 PR merged in Selectors spec (1 in February).
- 1 PR merged in HTML spec (1 in February).
Next steps #
First thing is to get the main patch landed in WebKit and verify that things are working as expected on the different platforms.
Another issue we need to solve is to reach an agreement on how script focus should work regarding :focus-visible
, and then get that implemented in WebKit covering all the cases.
After that we could request to enable the feature by default in WebKit. Once that’s done, we could discuss the possibility to change the default User Agent style sheet to use :focus-visible
too.
There are some interop work pending to do. A few things are failing on Firefox and we could try to help to fix them. Also some weird issues with <select>
elements in Chromium that might need some love too. And depending on the ongoing spec discussions there might be some changes needed or not in the different browsers. Anyway, we might find the time or not to do this, let’s see how things evolve in the next weeks.
Big thanks to everyone that has contributed to this project, you’re all wonderful for letting us work on this. 🙏 Stay tuned for more updates in the future!