DO NOT USE THIS PACKAGE. See @wicg/focus-ring
npm install debug-focus-ring
Based on the proposed CSS:focus-ring
pseudo-selector,
this prototype adds a focus-ring class to the focused element,
in situations in which the :focus-ring pseudo-selector should match.
npm install --save wicg-focus-ring
We suggest that users
selectively disable the default focus style
by selecting for the case when the polyfill is loaded
and .focus-ring is _not_ applied to the element:
``html`
.js-focus-ring :focus:not(.focus-ring) {
outline-width: 0;
}
If there are elements which should always have a focus ring shown,
authors may explicitly add the focus-ring class.blur
If explicitly added, it will not be removed on .
The status quo, :focus, is quite problematic:
- Many developers disable the default focus ring in their CSS styles,
others attempt to style it in concert with their design.
The former often seems to be a result of finding the default focus ring
both aesthetically unpleasant and confusing to users
when applied after a mouse or touch event and introduces accessibility problems.
The latter inevitably creates considerably more of the kind of problem that the former was trying to solve.
- Some native elements in some browsers,
notably
To deal with this:
- It seems evident that a visual indication of what has focus
is only interesting to a user who is using the keyboard
to interact with the page.
A user using any kind of pointing device
would only be interested in what is in focus
if they were _just about_ to use the keyboard -
otherwise, it is irrelevant and potentially confusing.
- Thus, if we only show the focus ring when relevant,
we can avoid user confusion
and avoid creating incentives for developers to disable it.
- A mechanism for exposing focus ring styles
only when the keyboard is the user's current input modality
gives us this opportunity.
`css
/ override UA stylesheet if necessary /
:focus {
outline-width: 0;
}
/ establish desired focus ring appearance for appropriate input modalities /
:focus-ring {
outline: 2px solid blue;
}
`
:focus-ring matches native elements that are
1. focussed; and
2. would display a focus ring if only UA styles applied
Additionally, :focus-ring matches non-native elements as if they were
native button elements.
This is not currently part of the spec,
but a mechanism is needed to explain the ability of native text fields
to match :focus-ring regardless of how focus arrived on the element.
Consider an author creating a custom element, custom-texty-element,:focus-ring
which they believe should show a focus ring on mouse click.
By default, the default user agent style:focus
will not show a focus ring when this element receives focus via mouse click.
However, if the author were to style the element via ,outline
they could not recreate the browser's default style reliably:
`css`
custom-texty-element:focus {
outline: ???;
}
Either of the following two new primitives would allow the author to
show the default focus ring on click for this element:
1. Add a new keyword value to the outline shorthand that represents whatever the default UA ::focus-ring is. Then authors can do:
custom-texty-element:focus {
outline: platform-default-focus-outline-style-foo;
}
2. Add a new CSS property that controls "keyboard modality" vs non-"keyboard modality" behavior, e.g.
custom-texty-element {
show-focus-ring-foo: always | keyboard-only;
}
_("-foo" placeholder indicates that these names are by no means final!)_
While either of these primitives would suffice,
having both would provide more flexibility for authors.
The heuristic used to decide the current modality should not be defined
normatively. An example heuristic is to update modality on each style recalc:
if the most recent user interaction was via the keyboard;
and the key pressed was either Tab or Shift + Tab;
then the modality is keyboard. Otherwise,
the modality is not keyboard.
The tiny
focus-ring.js
provides a prototype intended to achieve the goals we are proposing
with technology that exists today
in order for developers to be able to try it out, understand it and provide feedback.
It sets a .js-focus-ring class on the body element.focus-ring
to provide a way to disable focus styles only when the polyfill is loaded.
It also sets a class on the active elementblur
if the script determines that the keyboard is being used.
This attribute is removed on any event.
This allows authors to write rules
which show a focus style only when it would be relevant to the user.
Note that the prototype does not match the proposed API -
it is intended to give developers a feel for the model
rather than to provide a high-fidelity polyfill.
- a focus event immediately following a keydown event where the key pressed was either TabShift + Tab`.
or
- focus moves into an element which requires keyboard interaction,
such as a text field
- _TODO: ideally, we also trigger keyboard modality
following a keyboard event which activates an element or causes a mutation;
this still needs to be implemented._