Skip to content

Commit

Permalink
Make :focus-visible rules work when polyfill not present
Browse files Browse the repository at this point in the history
When the `focus-visible` polyfill is loaded—which it is in our LMS and
client projects—that polyfill will assign a `.focus-visible` class to
elements whose heuristics match the intent of `:focus-visible`, whether
or not the browser natively supports `:focus-visible` or not.

This rule, as previously written, was meant to suppress outlines on
elements if they didn't have the `.focus-visible` class:

```
&:focus:not(.focus-visible) {
  @include outline--hide;
}
```

The problem with this selector is that, if the polyfill is not
present, it will always match—because the `.focus-visible` class is
never present—causing all focus outlines to be suppressed, even when the
element is `:focus-visible`. That is, the previous selector was coupled
to the presence of the polyfill.

When present, the polyfill also applies a `.js-focus-visible` class to a
container element. We can make the selector here more specific, and
include that classname, such that it will only match when the polyfill
is actually present:

`.js-focus-visible &:focus:not(.focus-visible)`

Focus outlines "worked" before in the `lms` and `client` projects
because the polyfill was also present, but did not work in this project,
where we don't load the polyfill. Now this should work correctly in
both contexts.
  • Loading branch information
lyzadanger committed Jul 15, 2021
1 parent aa22822 commit e941fd6
Showing 1 changed file with 7 additions and 3 deletions.
10 changes: 7 additions & 3 deletions styles/mixins/_focus.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ $-color-focus-outline: var.$color-focus-outline;
*/
@mixin outline-on-keyboard-focus($inset: false) {
@include outline($inset);
// Selector for browsers using JS polyfill, which adds the "focus-visible"
// class to a keyboard-focused element.
&:focus:not(.focus-visible) {

// For browsers using the https://github.com/WICG/focus-visible polyfill,
// add a selector for the classname assigned by that polyfill to indicate
// :focus-visible equivalence for browsers that don't natively support it.
// The `.js-focus-visible` class indicates the presence of the polyfill,
// and is assigned to a container element.
.js-focus-visible &:focus:not(.focus-visible) {
@include outline--hide;
}

Expand Down

0 comments on commit e941fd6

Please sign in to comment.