Chrome 86 introduces two new features that improve both the user and developer experience when it comes to working with focus.
The :focus-visible pseudo-class is a CSS selector that lets developers opt-in to the same heuristic the browser uses when it's deciding whether to show a default focus indicator. This makes styling focus more predictable.
The Quick Focus Highlight is a user preference that causes the currently focused element to display an indicator for two seconds. The Quick Focus Highlight will always display, even if a page has disabled focus styles using CSS. It will also cause all CSS focus styles to match regardless of the input device that is interacting with the page.
The focus ring signals to the user which element will receive keyboard events. If a user is tabbing through a form, the focus ring indicates which text field they can type into, or if they've focused a submit button they will know that pressing Enter or Spacebar will activate that button.
For users who rely on a keyboard or other assistive technology to access the page, the focus ring acts as their mouse pointer - it's how they know what they are interacting with.
Unfortunately, many websites hide the focus ring using CSS. Oftentimes they do this because the underlying behavior of focus can be difficult to understand, and styling focus can have surprising consequences.
For example, a custom dropdown menu should use the tabindex attribute to make itself keyboard operable. But adding a tabindex to an element causes all browsers to show a focus ring on that element if it is clicked with a mouse. If a developer is surprised to see the focus ring when they click the menu, they might use the following CSS to hide it:
.custom-dropdown-menu:focus { outline: none; }
This "fixes" their issue, insofar as they no longer see the focus ring when they click the menu. However, they have unknowingly broken the experience for users relying on a keyboard to access the page. As mentioned earlier, for users who rely on a keyboard to access the page, the focus ring acts as their mouse pointer. Therefore, CSS that removes the focus ring (without providing an alternative) is akin to hiding the mouse pointer.
To improve on this situation, developers need a better way to style focus - one that matches their expectations of how focus should work, and doesn't run the risk of breaking the experience for users. At the same time, users need to have the final say in the experience and should be able to choose when and how they see focus. This is where :focus-visible and the Quick Focus Highlight come in.
Whenever you click on an element, browsers use an internal heuristic to determine whether they should display a default focus indicator. This is why in Chrome tabbing to a <button> shows a focus ring, but clicking it with a mouse does not.
When you use :focus to style an element, it tells the browser to ignore its heuristic and to always show your focus style. For some situations this can break the user's expectation and lead to a confusing experience.
:focus-visible, on the other hand, will invoke the same heuristic that the browser uses when it's deciding whether to show the default focus indicator. This allows focus styles to feel more intuitive. In Chrome 86 and beyond, this should be all you need to style focus:
/* Focusing the button with a keyboard will show a dashed black line. */ button:focus-visible { outline: 4px dashed black; }
By combining :focus-visible with :focus you can take things a step further and provide different focus styles depending on the user's input device. This can be helpful if you want the focus indicator to depend on the precision of the input device:
/* Focusing the button with a keyboard will show a dashed black line. */ button:focus-visible { outline: 4px dashed black; } /* Focusing the button with a mouse, touch, or stylus will show a subtle drop shadow. */ button:focus:not(:focus-visible) { outline: none; box-shadow: 1px 1px 5px rgba(1, 1, 0, .7); }
The snippet above says that if the browser would normally show a focus indicator, then it should do so using a 4px dashed black outline. Additionally, the example relies on the existing :focus behavior and says that if an element has focus, but the browser would not normally show a default focus ring, then it should show a drop shadow.
Since the browser doesn't usually show a default focus ring when a user clicks on a button, the :focus:not(:focus-visible) pattern can be an easy way to specifically target mouse/touch focus.
Note that not all browsers set focus in the same way, so the above snippet will work in Chromium based browsers, but may not work in others.
Understanding the browsers’ heuristics for focus indicators will help you understand when to use :focus-visible. Unfortunately, the heuristic has never been specified, so the behavior is subtly different in every browser. The :focus-visible polyfill. Once the polyfill is loaded, you can use the .focus-visible class instead of :focus-visible to achieve similar results:
/* Define mouse/touch focus indicators. */ .js-focus-visible :focus:not(.focus-visible) { … } /* Define keyboard focus indicators. */ .js-focus-visible .focus-visible { … }
Note that the MDN support table shows Firefox supports a similar selector known as :-moz-focusring which :focus-visible is based on; however the behavior between the two selectors is quite different and it's recommended to use the :focus-visible polyfill if you need cross-browser support.
:focus-visible makes it easier for developers to selectively style focus and avoids pitfalls with the existing :focus selector. While this is a great addition to the developer toolbox, for a subset of users, particularly those with cognitive impairments, it can be helpful to always see a focus indicator, and they may find it distressing when the focus indicator appears less often due to selective styling with :focus-visible.
For these users, Chrome 86 adds a setting called Quick Focus Highlight.
Quick Focus Highlight temporarily highlights the currently focused element, and causes :focus-visible to always match.
To enable Quick Focus Highlight:
Go to Chrome's settings menu (or type chrome://settings into the address bar).
Click Advanced then Accessibility.
Enable the toggle switch to Show a quick highlight on the focused object.
Once Quick Focus Highlight is enabled, focused elements will show a white-blue outline with a blue glow. (See the image below.). The Highlight uses these alternating colors to ensure that it has proper contrast on any background.
The Highlight is outset from the focused element to avoid interfering with that element's existing focus styles or drop shadows. The Highlight will fade out after two seconds to avoid obscuring page content, such as text.
Because :focus-visible uses the same heuristic as a default focus indicator, the experience should match what users expect on these platforms when they interact with unstyled HTML elements.
In other words, if developers use :focus-visible as their primary means to style focus, then the experience should be more consistent for all users regardless of their input device.
Most of the time, :focus-visible matching only indicates that a user is using the keyboard, or has focused an element which takes text input.
:focus-visible could potentially be used to detect that a user has enabled a preference to always show a focus indicator, by tracking mouse and keyboard events and checking matches(":focus-visible") on elements which were focused when the keyboard is not being used. Since the precise details of when :focus-visible should match are left up to the browser's implementation, this would not be a completely reliable method.
:focus-visible and the Quick Focus Highlight were designed to work together to help these users.
:focus-visible aims to address the common anti-pattern of developers removing the focus indicator from all of their controls. Using the browser's focus heuristic helps by creating fewer surprises for developers when the focus ring appears, meaning fewer reasons to use CSS to hide the ring.
For some users the browser's default behavior may still be insufficient. They may want to see a focus ring regardless of the type of control they're interacting with, or the input device they're using. That's where the Quick Focus Highlight can help.
The Quick Focus Highlight lets users increase the visibility of the focus indicator, and makes it so :focus-visible always matches, regardless of their input device. This combination of effects should make the currently focused element much easier to identify.
The Quick Focus Highlight does not currently support an "always on" mode because it's difficult to design a universal focus overlay that does not obscure page content. As a result, the Highlight will fade out after two seconds, and rely on either the browser's default focus indicator, or the page author's :focus and :focus-visible styles.
Because the Highlight is a user preference its behavior can be changed in the future if users would prefer that it always stay on.
There has been discussion around adding :focus-visible-within, but a proposal will require additional use cases. If you feel like you have a good use case for :focus-visible-within file a chromium bug.