Removing that ugly :focus ring (and keeping it too)

David Gilbertson
5 min readAug 5, 2017

You know how it goes, you’ve got a carefully crafted design that is just the way you like it (uh huh uh huh).

But then this happens:

You click a button and see a blue border telling you that you’ve clicked on something that you know perfectly well you’ve just clicked on — because you just clicked on it.

So it’s clear: the outline must go.

button:focus { outline: none; }

[brushes hands theatrically]

But hold on a minute, what about those users that don’t/can’t use a pointing device? They might be tabbing around the page to focus particular elements — and now they can’t tell which element is currently focused.

Removing the focus outline is like removing the wheelchair ramp from a school because it doesn’t fit in with the aesthetic.

So Beyoncé was right all along, we shoulda put a ring on it.

It would seem we have a showdown.

In one corner those folks that want the web to be accessible, and in the other, those fancy designer types that want the web to be pretty.

Whatever is a poor web developer to do?

Unlike absolutely everything else in life, when it comes to focus rings it is indeed possible to please all of the people, all of the time.

And it’s super easy.

Identifying keyboard navigators

For you see, gentle reader, there is a special button that all keyboard navigators will press to inform you that they plan to be using the keyboard to move around your site.

And so we wait. And we listen. And when the user presses this button, we pounce, and add a class to the body.

Check your browser support requirements before copy/pasting this one.

Now we can hide the ugly blue outline for everyone except the users that have hit the “I am a keyboard user” key (sometimes called the ‘tab’ key).

That’s literally all there is to it. 13 lines.

/u/here-for-karma wisely pointed out on Reddit that if you want to cater for those with no JavaScript, you can simply start with the user-is-tabbing class applied to the body, then remove it as soon as you see some mouse action (don’t forget mobile users who may not fire a mousemove event). This would also handle the situation of someone navigating without the mouse, but without the tab key (if this is even possible, I don’t know).

End of blog post.

[Author leans back, puts feet on desk and starts puzzling over a Rubik’s Cube. Sensing there are still people in the room, he looks up…]

Oh hey there, what are you still doing here?

Oh, you want to complicate things unnecessarily?

You want to handle the super-duper edge case where a user starts tabbing, but then begins using the mouse. You then want to start hiding the blue focus ring again, rather than continue to show the outline because that would surely be the end of the world.

I disapprove, but I support your right to do things the wrong way.

I only disapprove because of a personal distaste for complexity.

We listen for the first press of the tab key, then add the user-is-tabbing class to the body. Then we start listening for a mousedown event, and if that occurs, we remove the user-is-tabbing class from the body, and start listening for tab again.

Easy peasy.

(Performance note: running this handleFirstTab function on every key press might be a performance concern for you. It takes about 5 microseconds — so if you think your users will notice a 5 microsecond delay (which would be impressive since a display typically only updates every sixteen thousand microseconds) then I’d steer clear of this approach.)

End of blog post.

Thanks for reading. You’ve all been great.

[Author plops down in a lounge chair, retrieves a foot-long Toblerone from under a cushion and snaps off a triangle. Sensing someone is still in the room, he turns around sharply...]

Oh what is it now?

You want to have a subtle focus style for mouse users, when they have clicked on a keyboard-entry element (e.g. <input type="text"> or <textarea>). And remove other focus rings, but then for the keyboard navigators show the normal focus ring.

Excellent choice, this is what I do, too.

For this let’s flip the logic. First, we’ll either hide the focus ring, or make it something more subtle.

Next, for the users who are tabbing, we’ll show something that stands out a little more. I haven’t found a good way to ‘reset’ to focus ring for all browsers, but the webkit approach covers most users and the fallback looks fine if you ask me.

Accessibility is !important!

You may have heard that box-shadow is a good way to replicate that blurry outline, but thanks to Tim in the comments, I now know that a <select> can’t have a box-shadow in Safari. Edit, and thanks

Here’s a general approximation of what I use in the projects I work on:

Wrapping up

Some might say this is bad for accessibility because it promotes doing something other than just leaving the big blue border everywhere. But the reality is, it’s 2017 and the focus outline is hidden on most sites.

It’s not great, but it is what it is. Any improvement on the status quo is a win for accessibility — and that’s what I’m hoping for.

It might not be perfect, but it’s simple stuff. It’s something you can go and do right now without even asking your product managers, designers, etc.

In fact, it’s so simple that the first person to think of this probably wrote a blog post about it several decades ago. But for a brief period of time I will be the most recent person to write a blog post about it.

One particular piece of prior art I would like to point to is Alice Boxhall’s article from two years ago which is a much more sophisticated approach to the same problem.

If you’ve got something to add, let me know. I’ve learnt a few interesting things from comments already and will continue to update the article as I learn more.

End of blog post.

[Author pulls sombrero down over his face, slips off his Mexican pointy boots, and descends into slumber.]

--

--