Wanna see something cool? Check out Angular Spotify 🎧

The different between :focus and :focus-visible

Problem

Browsing the web using different input methods like a mouse, keyboard, or assistive technology devices requires clear indicators of the current interactive element for a good user experience and accessibility. While default browser stylesheets do a great job, there are cases where we may want more control over focus styling.

The difference between :focus and :focus-visible

One common argument against focus indicators is that they appear even when you click on a component with a mouse or tap on it. Designers and stakeholders often don’t prefer this behavior.

Currently, modern browsers only show default focus indicators when necessary, specifically when navigating with a keyboard. The focus outline doesn’t show up when an element is clicked or tapped; it only appears when tabbing to it using a keyboard.

Understanding the Issue

In the provided 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 and a transform(1.5) to the element to make the focus state visually obvious.

The problem arises when:

  • Navigating with the keyboard, both the outline and the element grow bigger with transform.
  • Clicking with the mouse, the outline is invisible, but the element still grows bigger with transform. This behavior is not desired.

The difference between :focus and :focus-visible

Somehow, when we click, it also captures the focus state.

You may wonder 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.

To solve this issue and show focus indicators only for users who need them, we can use the :focus-visible selector.

What is :focus-visible?

:focus-visible works just like :focus, but it only applies focus indicator styles to an element when it receives keyboard focus.

Now, the focus indicator will only be visible to users navigating with a keyboard or keyboard-like assistive technology. Users who aren’t using a keyboard won’t even know it’s there!

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

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

The difference between :focus and :focus-visible

Browser Support

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

The difference between :focus and :focus-visible

Support notes — March 2023

The :focus-visible pseudo-class is now supported in all major browsers.

But we recommend that default :focus styles are still provided, as a fallback for older versions, since focus indication is so critical.

Read more for more details and an alternative :focus:not(:focus-visible)

Key Takeaways

If you want to display focus indicators only for keyboard users, utilize 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 @trungvose on Twitter for more!