UNPKG

4.98 kBMarkdownView Raw
1- [Rationale](#rationale)
2- [API Proposal](#api-proposal)
3 * [Note: Styling non-native elements which should always match `focus-visible`](#note--styling-non-native-elements-which-should-always-match--focus-visible-)
4- [Example heuristic](#example-heuristic)
5- [Implementation Prototype](#implementation-prototype)
6
7## Rationale
8
9The status quo, `:focus`, is quite problematic:
10
11- Many developers disable the default focus ring in their CSS styles,
12 others attempt to style it in concert with their design.
13 The former often seems to be a result of finding the default focus ring
14 both aesthetically unpleasant and confusing to users
15 when applied after a mouse or touch event and introduces accessibility problems.
16 The latter inevitably creates considerably more of the kind of problem that the former was trying to solve.
17- Some native elements in some browsers,
18 notably `<button>` in Chrome,
19 have a "magic" focus style which does _not_ apply
20 unless focus was received via a keyboard interaction.
21
22To deal with this:
23- It seems evident that a visual indication of what has focus
24 is only interesting to a user who is using the keyboard
25 to interact with the page.
26 A user using any kind of pointing device
27 would only be interested in what is in focus
28 if they were _just about_ to use the keyboard -
29 otherwise, it is irrelevant and potentially confusing.
30- Thus, if we only show the focus ring when relevant,
31 we can avoid user confusion
32 and avoid creating incentives for developers to disable it.
33- A mechanism for exposing focus ring styles
34 only when the keyboard is the user's current input modality
35 gives us this opportunity.
36
37## API Proposal
38
39```css
40/* override UA stylesheet if necessary */
41:focus {
42 outline: 0;
43}
44
45/* establish desired focus ring appearance for appropriate input modalities */
46:focus-visible {
47 outline: 2px solid blue;
48}
49```
50
51`:focus-visible` matches native elements that are
521. focussed; and
532. would display a focus ring if only UA styles applied
54
55Additionally, `:focus-visible` matches non-native elements as if they were
56native button elements.
57
58### Note: Styling non-native elements which should always match `focus-visible`
59
60
61This is not currently part of the spec,
62but a mechanism is needed to explain the ability of native text fields
63to match `:focus-visible` regardless of how focus arrived on the element.
64
65Consider an author creating a custom element, `custom-texty-element`,
66which they believe should show a focus ring on mouse click.
67By default, the default `:focus-visible` user agent style
68will not show a focus ring when this element receives focus via mouse click.
69However, if the author were to style the element via `:focus`,
70they could not recreate the browser's default `outline` style reliably:
71
72```css
73custom-texty-element:focus {
74 outline: ???;
75}
76```
77
78Either of the following two new primitives would allow the author to
79show the default focus ring on click for this element:
80
811. Add a new keyword value to the outline shorthand that represents whatever the default UA `::focus-visible` is. Then authors can do:
82
83 custom-texty-element:focus {
84 outline: platform-default-focus-outline-style-foo;
85 }
86
872. Add a new CSS property that controls "keyboard modality" vs non-"keyboard modality" behavior, e.g.
88
89 custom-texty-element {
90 show-focus-visible-foo: always | keyboard-only;
91 }
92
93_("`-foo`" placeholder indicates that these names are by no means final!)_
94
95While either of these primitives would suffice,
96having both would provide more flexibility for authors.
97
98## Example heuristic
99
100The heuristic used to decide the current modality should not be defined
101normatively. An example heuristic is to update modality on each style recalc: if
102the most recent user interaction was via the keyboard; and the key press did not
103include a meta, alt/option, or control key; then the modality is keyboard.
104Otherwise, the modality is not keyboard.
105
106See [the web platform
107tests](https://github.com/web-platform-tests/wpt/search?utf8=%E2%9C%93&q=focus-visible&type=)
108which check against the proposed behavior.
109
110## Implementation Prototype
111
112The tiny
113[focus-visible.js](https://www.npmjs.com/package/focus-visible)
114provides a prototype intended to achieve the goals we are proposing
115with technology that exists today
116in order for developers to be able to try it out, understand it and provide feedback.
117It sets a `.js-focus-visible` class on the body element
118to provide a way to disable focus styles only when the polyfill is loaded.
119It also sets a `.focus-visible` class on the active element
120if the script determines that the keyboard is being used.
121This attribute is removed on any `blur` event.
122
123This allows authors to write rules
124which show a focus style only when it would be relevant to the user.
125Note that the prototype does not match the proposed API -
126it is intended to give developers a feel for the model
127rather than to provide a high-fidelity polyfill.