Brainstorm: options for opting in to always matching focus ring
We know we need a way to opt an element in to always (or never?) getting a focus ring. Let's talk about strategies for doing this.
Proposal: just use :focus
Use the existing :focus pseudo-selector to opt an element in to always getting a focus ring on focus. Requires a way to recover the platform default focus style, assuming :focus-ring will be the UA default in future (which we should probably provide in any case).
Example
custom-text-editor:focus {
outline: platform-default; /* need a way to express this */
}
Pros
- Potentially makes the mental model of
:focus-ringeasier to understand - Could use same strategy in UA stylesheet, e.g.
input[type=text]:focus
Cons
- No scope for any more nuanced matching options
- Requires an extra concept (albeit one we probably want anyway) to allow re-enabling the platform default focus ring.
Proposal: add a new CSS property to express when an element should match :focus-ring
Allow an element to opt in to :focus-ring matching the way built-in text editing elements do. Potentially also allows fine tuning focus-ring matching at page author discretion.
Example (all syntax to be considered a "straw man")
custom-text-editor {
show-focusring: always;
}
div[tabindex=-1] {
show-focusring: never; /* may potentially be overridden by user preference */
}
* {
/* match when focus is moved via the keyboard explicitly, i.e. tab/shift-tab */
show-focusring: explicit-focus;
}
button {
show-focusring: on-keypress;
}
Pros
- More nuance possible
cc @shans
@alice I think your 2nd proposal is far far better than pursuing the current :focus-ring implementation; it's more robust.
- Allows for fine grain control over when the focus ring is displayed; solving for all of the various niche cases discussed in #33
- Makes it much easier for authors to preserve browser default focus styles (should they want to)
- Feels more with-the-grain of CSS; reminds me of how
overflowworks.
Nice one.
I like the second proposal if we can get buy-in. And I also want outline: platform-default; :)
@alice @robdodson what's the next step for moving on @alice's proposal?
@kloots I think one thing alice and I were unsure of: were you saying you like the second proposal instead of :focus-ring or in addition to :focus-ring? In other words, were you suggesting we drop :focus-ring entirely and pursue that other proposal?
@robdodson yeah, I really like @alice's second proposal and think it'd be better for the industry if we pursued that over :focus-ring.
To clarify: this was always intended to be as well as :focus-ring, and affect when :focus-ring matches. :focus can't be changed at this point (believe me, we went around and around on this previously).
The full story would then hopefully look like:
- Browsers provide a default
:focus-ringstyle in the UA stylesheet. - Authors may override that style if they wish.
- Authors may use
outline: platform-default(whatever it ends up being called) to reset the outline style further on down the cascade. - Authors may also fine-tune when they wish certain elements to match
:focus-ring. -
:focuswill continue to match any active element.
@alice thanks for the clarification. Man, sorry to hear :focus cannot be changed because that's the obvious pseudo-selector everyone knows about. Giving developers a new CSS prop that would allow authors to fine tune when it matches and what it looks like seemed really with the grain of how other things in CSS already work; like when border-radius was introduced years back.
Next steps:
- Write up full proposal for
show-focusring(whatever we call it) property - Figure out the status of outline-style, which allows recovering the platform outline style if used correctly
- Propose
:focus-ringandshow-focusringat CSS WG in Paris in August.
I really like the way this is going. It seemed difficult to support all necessary use cases with :focus-ring alone, and this provides a lot more control for handling focus states within a deep cascade. We'll have a challenge explaining why :focus couldn't be used no matter which way we go, so at least if the APIs allow us to achieve more detailed focus we'll be successful at getting UI jobs done (and then relaying to others how we did it). Curious to hear how the proposal goes over with the CSS WG.
regarding this example:
custom-text-editor:focus {
outline: platform-default; /* need a way to express this */
}
I just learned about the revert value. It looks like only Safari supports it but I think this might be what we want.
@robdodson nice one!
I'm really glad to see this conversation happening: Early on I posited that we needed more than just :focus-ring with a simple modality switch as there are things that just don't/can't automatically be mapped cleanly to existing concepts: custom elements and pretty much anything with a tabindex=-1 present interesting challenges that seem like they have to somehow be component specified at least, possibly left then further to individual authors. It's possible that using the above we could work custom attributes into the mix to signal which path to follow - the original implementation had something like that (so does my company's fork iirc for this reason), though @alice's breakdown seems better. I'm very pro us experimenting with this in the polyfill if we can as so far it does seem we're getting useful feedback that is much better to get now than once we're shipping a real thing.
Just wanted to add my support for @alice's proposal for show-focusring which is a really nice idea.
Just a quick update, see the last part of this comment for details. https://github.com/WICG/focus-visible/issues/88#issuecomment-398518020
Per Alice's earlier comment about styling the focus ring to match the platform default. It seems like you can kind of do this today, using outline: auto, but it doesn't get the color right.
:focus-visible {
outline: auto;
}

To recreate the specific color used in Chrome requires using -webkit-focus-ring-color.
:focus-visible {
outline: auto -webkit-focus-ring-color;
}

I wonder if it would be possible to encourage other browsers that implement :focus-visible to also expose a CSS variable that contains all of the appropriate styles. Then you could do:
:focus-visible {
outline: var(--default-focus-ring)
}
I wonder if it would be possible to encourage other browsers that implement
:focus-visibleto also expose a CSS variable that contains all of the appropriate styles.
Even if we are gonna do this it should be a new keyword instead of a custom property IMO.
I noticed Chrome's stylesheet uses a single dash -webkit-focus-ring-color and not the double dash syntax for custom properties, --webkit-focus-ring-color. I'm curious if browsers have the notion of a variable that's public but not configurable.
They are the same syntax actually. -vendor- has always been the model. Custom properties created be the author just have no vendor.
Custom preoperties(aka “CSS variables”), as the name says, are properties which require var() to call the values. -webkit-focus-ring-color is just a value keyword with a vendor prefix, not a “variable”. I think using revert should be the most proper way to restore the UA style but before it’s implemented in Chrome something like -webkit-focus-ring-color is also acceptable.
@alice Has there been any movement on this recently? Would love to gain some momentum across vendors for supporting your proposal.
Some more discussion here: https://github.com/w3c/webcomponents/issues/762