Wanna see something cool? Check out Angular Spotify 🎧

The different between :focus and :focus-visible

Problem

You can browse the Web using a mouse, keyboard and all sorts of assistive technology devices. Whichever input method you use, a clear indication of the current interactive element is crucial for a good user experience and accessibility. Default browsers stylesheets do a great job at it, but sometimes we want to be a little bit more sophisticated, or at least different.

The different between :focus and :focus-visible

The use case that you might have encountered is when you want to style the focus state of an element, but you don’t want to apply the same style to the focus state of a mouse click. This is where the :focus-visible pseudo-class comes in handy.

See the following code and example.

&:hover {
  background: red;
  color: white;
}

&:focus {
  outline-color: #007dbc60;
  outline-offset: 0.5rem;
  transform: scale(1.5);
}

We applied a different outline color on focus, and at the same time we applied a transform(1.5) to the element. So that it looks obvious when the element is focused.

That’s where most of us see the problem.

  • When I use the keyboard to navigate, you see both the outline and the element grow bigger with transform.
  • But when I use the mouse to click, you don’t see the outline but the element still grow bigger with transform. We don’t want that.

The different between :focus and :focus-visible

Somehow when we click, it captures the focus state as well.

You might wondering why only the scale is applied, but not the outline?

The reason is that the outline is a property that is only visible when the element is focused using focus-visible under the hood. So when we click, the outline is not visible, but the scale is still applied.

What is :focus-visible?

:focus-visible is a pseudo-class that matches when an element matches the :focus pseudo-class and the user agent determines via heuristics that the focus should be made evident on the element. In other words, it matches when an element matches the :focus pseudo-class, but only if the focus ring or other indicator should be drawn for that element.

To fix the issue above, we can simply change :focus to :focus-visible in our CSS.

- &:focus {
+ &:focus-visible {
  outline-color: #007dbc60;
  outline-offset: 0.5rem;
  transform: scale(1.5);
}

The different between :focus and :focus-visible

Browser support

The :focus-visible pseudo-class is supported by all major browsers, except for IE11.

The different between :focus and :focus-visible

Takeaways

If you want to style the focus state of an element, but you don’t want to apply the same style to the focus state of a mouse click, you can use the :focus-visible pseudo-class instead of :focus.

Source code

Published 19 Nov 2022

    Read more

     — Angular 13 upgrade - Error: Unknown keyword formatMinimum
     — ngIf - Store the conditional result in a variable
     — Common use cases and solutions for accessibility in Angular
     — Error: Cannot install in Homebrew on ARM processor in Intel default prefix (/usr/local)
     — /usr/local/bin/code: line 6: python: command not found

    Follow @tuantrungvo on Twitter for more!