:focus-visible
in WebKitDiscussion around what happens when the user focus an element via mouse click, and if it'd be fine not showing a focus ring in that case.
For elements that support keyboard input (like INPUTs, TEXTAREAs, contenteditable
) there's no doubt that the browser should show a focus ring when they're focused via mouse click (that's what all browsers do).
However the cuestion comes when we have other focusable elements that don't receive keyboard input.
In Safari when you click a link or a button via mouse click, the element doesn't get focused, so it doesn't show a focus ring. However with that mouse click, an invisible selection caret is moving to that element, so if the user uses keyboard navigation next (tab or option+tab) the next focused element will be the one after where the mouse have clicked (see example).
That can be confusing to Windows users developing for the Mac, as the first click has moved the insertion point (tab navigation context), but not the focus. However, this is the way Mac OS has been working forever and Mac keyboard users expect the behavior to remain.
As a side note, we seem to agree that Linux and Windows WebKit ports could change the current behavior with buttons (they're focusable on those platforms) as they're showing a focus ring on mouse click, it'd be fine to not show it by default.
So the key question was around what should happen when the user clicks on a <div tabindex=0>
.
Right now WebKit shows a focus ring on that element, but the purpose of :focus-visible
feature is somehow to avoid that and only show the focus ring on keyboard navigation.
A simple <div tabindex=0>
is too ambigous and the browser cannot try to guess what's the web author intention, so not showing a focus ring by default here seems kind of dangerous.
So we came up with the idea of not showing it for some specific roles, like for example a button or a heading (specific list to be defined), and in those cases not show the focus ring on mouse click. That would give web authors the chance to opt-in into this behavior.
For example if someone is creating a "button" with <div tabindex=0>
and they're getting bothered by the focus ring showed on mouse click, they would just need to add the proper role to the element and it won't be showed, something like <div tabindex=0 role=button>
. We could even consider implicit roles like headings and so on here.
This will be a behavior change regarding focus ring in Safari on elements like <div tabindex=0 role=button>
, so this would need a clear agreement on the Apple side and proper testing. At the same time this will make <div tabindex=0 role=button>
to behave similar to a native button on Safari from the user POV.
Update May 14: One example not discussed yesterday is the default Space Bar behavior when an activatable element is focused.
Similarly up/down arrow keys scroll the page by default, but modify certain controls (an <input type="range">
slider, for example) when the control gets keyboard focused. The same is not true when these controls are modified with the mouse, as keyboard focus never moves to the control.
From a related thread: "For authors who want a control that participates in the tab focus cycle, but without drawing a focus ring on tap or click, [a better solution may be] to give them a way to make a elements keyboard-focusable but not mouse-focusable. I don't think there's any support in the web platform for that, although the opposite is possible with tabIndex=-1."
Here everyone agrees that you should show a focus ring by default and match :focus-visible
.
The hard part is defining what's exactly "support keyboard input".
Things like INPUTs, TEXTAREAs and contenteditable
elements are clear fits in this category.
Other things like SELECT (or other elements) could vary depending on the browser. So we could make or own decissions in WebKit rearding this.
For example, <div tabindex=0 role=listbox>
looks like a clear candidate to be part of this list.
Here everyone agrees too, if the user is using the keyboard to navigate the page, we should always show a focus ring, and this should always match :focus-visible
.
When this happens, unless it's one of the elements with a pretty clear answer (see first point), it is hard to know what to do by default since there is no universal "right". Data shows authors doing :focus { outline: none; }
to avoid this happening too often when they think it shouldn't, which is worse.
When you click <div tabindex=0>
there are a lot of "false positives", this was one of the main reasons to add :focus-visible
. Rob Dodson (Google) would have a bunch of examples where this is important, but there are a lot where a ring isn't necessary because the presence or style of div itself is the affordance (a dialog, popup, or some tabs are easy to visualize examples of this where the intent of actually focusing might even be simply 'move the fnsp (focus navigation starting point)')
Ideally we could agree on UA sheets themselves employing :focus-visible
here and agreeing and the defaults would then match too - but it looks like we might not want to do that in WebKit, and we'd prefer to show the ring by default always except some specific cases (like for example <div tabindex=0 role=button>
). The question is, if we can't get things close enough to be satisfied, can we give authors more predictable powers via :focus-visible
that avoid just turning them off.
This a controversial issue, in Chromium if you enter some letter (after you have focused an element), the focused element will start matching :focus-visible
(independently of the type of element or if it was matching that before or not).
The rationale behind this behavior is mostly a user affordance, so the user can at some point type a letter to find where the focus is. Normally just sequentially advancing and moving back is the right move, but there are some controls where that won't work because focus is programatically maintained.
Chromium implements this, but Firefox doesn't.
We do have an implementation of this behavior in WebKit but we could get rid of it if we believe this is not something we want.
This is to decide what to do when a script move focus elsewhere.
Right now all 3 implementations have the very same behavior, covered by a bunch of tests.
The behavior is:
This kind of things are needed to deal with clicks on BUTTONs that move focus to some place. Authors have complained about the presence of focus ring on that scenario, and have used :focus { outline: none; }
to disable it. More info at https://github.com/w3c/csswg-drafts/issues/5885#issuecomment-769988872 and https://github.com/WICG/focus-visible/issues/88#issuecomment-398518020.
There are still some extra improvements that could be done here, but neither of the browsers implement that yet. More info at: https://github.com/web-platform-tests/wpt/issues/28505
Do we want to add a WebKit preference to always see a focus ring? Chromium added this, along with an improvement where the indicator isn't constant and rationale for that. It seems good.
If the preference is set, you'll always see a focus ring on the focused element, so :focus-visible
will always match.
Probably we should add something like this on WebKit, or maybe use some existent preference to enable this behavior too.