Focus Style for Keyboard Navigation Only
Tags: a11y, javascript, css
Published: 2019-04-25 22:14:29

---
title: Focus Style for Keyboard Navigation Only
published: true
description: How to target user using Keyboard so that we can provide a better focus indication for them
tags: a11y, javascript, css
---

_I had the idea of this post after reading this one [Designing button focus states for better usability](https://dev.to/elizabethschafer/designing-button-focus-states-for-better-usability-gm2), if you haven't read it yet, go for it._

## Accessibility vs UI

_Well, I didn't really want to oppose a11y to UI as a fight but couldn't come up with a better name._

Sometimes, you might want to remove the default outline the browser will provide for free. When you do that, you certainly please your designers, but you're making it hard for people who rely on assistive technologies, or keyboard navigation.

With `:focus-visible` ([Specs in Working Draft](https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo)) you can make both sides happy. I still wouldn't recommend to remove the whole outline on `:focus` on every element of your app because it can still benefit and help some users.

Though, there are some cases where the focus ring might not be great in your UI, the ones I can think of would be clickable icons, e.g. arrows ← → for pagination, hamburger icon to open a menu.

![Example of a click on a hamburger icon to open a menu which also shows the native outline focus ring](https://thepracticaldev.s3.amazonaws.com/i/3jor5g4faqcnnlqvzqh7.gif)

Also, in the case of a custom style `<button>` having a high `border-radius`, the `outline` won't follow the rounded corners, and will result in this:

![button with native outline when focused](https://thepracticaldev.s3.amazonaws.com/i/8a4bqfjcandkriw5tey2.png)

**When clicking with a mouse or tap with your finger** the added value of this focus ring is low (`:hover` and `:active` are probably better candidates), and it even adds useless noise to the UI. On the other hand, when tabbing through a website, users need to know that the focus is on the hamburger icon so that they can open the menu.

## :focus-visible To The Rescue

The main difference between the two `:focus` and `:focus-visible`, is that you can use 
`:focus-visible` for people not navigating with a pointing device (mouse, touch, etc...).
That means that we can target people relying on keyboard navigation.

As of April 2019, it's implemented in Chrome only **and** behind a flag. However the good news is that if we still want to use this, we still can by using a polyfill [github.com/WICG/focus-visible](https://github.com/WICG/focus-visible).

If in your codebase, you can remove the `outline : none` that you had, install this polyfill, and update your CSS with this (as a first step)

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

**This selector will filter out all the elements focused by a keyboard event, and won't apply in that case, so you can keep the default `outline` by default.**

A little detail that I really like in this spec is that `:focus-visible` also applies in case the user focuses an `<input>` field either with a mouse or a keyboard. Why? The rule is simple, if an interactive element opens the keyboard (on a mobile) it should keep the focus ring. I completely agree with this, even on desktop having an indication on where your caret is, can only be a good thing.

A workmate showed me this great example on how to get crazy with focus for keyboard navigation, there even are animations based on the direction when you navigate: [sbb.ch/en/home.html](https://www.sbb.ch/en/home.html)

So let's end this era of `:focus { outline: none; }` now that we have a reliable solution that works for everyone and can benefit to lots of people.

---

### _Ressources_

A good read on the intent behind `focus-visible`:
[github.com/WICG/focus-visible/issues/128](https://github.com/WICG/focus-visible/issues/128)

Specifications:
[drafts.csswg.org/selectors-4/#the-focus-visible-pseudo](https://drafts.csswg.org/selectors-4/#the-focus-visible-pseudo)