DEV Community

Gaurav Soni
Gaurav Soni

Posted on

Enhance a11y using :focus-visible pseudo-class

Accessibility is one of the important aspects of the applications. Building the accessible applications will make sure your application will be used by all people(irrespective of their disabilities). According to W3C,

The Web is fundamentally designed to work for all people, whatever their hardware, software, language, location, or ability. When the Web meets this goal, it is accessible to people with a diverse range of hearing, movement, sight, and cognitive ability.

Problem Statement

In order to make our web pages accessible, sometimes we need to explicitly set the focus on some non-interactive elements(headings, table, main etc) so that it will be read out by screen-readers. But by doing so we might also annoy our regular users(users who will not use screen readers). Normal users can read the text easily. It would be good if there is a way to make the non-interactive elements focusable only for keyboard users or screen-readers.

:focus-visible is the rescue

From MDN,

The :focus-visible pseudo-class applies while an element matches the :focus pseudo-class and the UA (User Agent) determines via heuristics that the focus should be made evident on the element. (Many browsers show a “focus ring” by default in this case.)
This selector is useful to provide a different focus indicator based on the user’s input modality (mouse vs. keyboard).

I hope this will make sense now. The syntax to use it looks like:-

.element:focus-visible {
  /* Add some styles to get the user's attention */
}
Enter fullscreen mode Exit fullscreen mode

With this, we can add styles to focus on keyboard input. But this is not enough for what we want. For mouse users, we need to remove the focus styles from non-interactive elements,

.element:focus {
  outline: none;
}
Enter fullscreen mode Exit fullscreen mode

Now when the user tab on the element(make sure to add tabindex on non interactive elements), the element will get the focus but if we mouse click to the element, the element will not get the focus. You can check this very basic example.

Now we have the :focus-visible pseudo-class. But there is again an issue. This selector is supported by chrome, firefox, and edge but not by safari. But thanks to the polyfill.
With this polyfill, it will be supported by all major browsers. But we need to slightly update the code.

/*
  This will hide the focus indicator if the element receives focus via the mouse,
  but it will still show up on keyboard focus.
*/
.element:focus:not(.focus-visible) {
  outline: none;
}

.element.focus-visible {
 /* Add some styles to get the user's attention */
}
Enter fullscreen mode Exit fullscreen mode

You may have noticed that instead of using the pseudo-class, we are using the class .focus-visible that is provided by the polyfill. With this change, we are all set to use this browser feature.

Learn more:-

Top comments (1)

Collapse
 
bhargavshah profile image
Bhargav Shah • Edited

Good to know this hack. In general it is considered a good practice to only focus on interactive items on a page. There are controls other than Tab key that AT and screen readers have to reach other parts of a webpage.

Source: "Items that should not receive keyboard focus" section of webaim.org/techniques/keyboard/