Removing :focus outline without destroying accessibility

Working with forms and buttons, there's a thing that often comes up when implementing the different states; the blue focus outline. It's there to let users know where the focus on the page is, and it's essential for keyboard navigation.

For some designs though, it might not be desired. Maybe you're into more subtle effects, maybe you're working with a designer who is. Well, being a crafty person, you can simply decide to hide it and be done with it.

/* Don’t do it */
:focus {
    outline: 0;
}

This solves the cosmetic issue, but while doing so it also completely destroys keyboard navigation. The user can't see where focus is, which is comparable to hiding the cursor for users who use a mouse.

The simple solution to the problem is to just not do it. Leave the outline and accept it – with time you might even learn to like it. If you do remove it, you are responsible for ensuring that the focus states are visible to the users who need them. We can infer that the user wants to see the focus states if they press the tab key, and hide them again if the user clicks with the mouse. This can be done with the following JavaScript:

window.addEventListener('keydown', ev => {
    if (ev.key === 'Tab') {
        document.documentElement.classList.add('tabbed');
    }
});

window.addEventListener('mousedown', () => {
    document.documentElement.classList.remove('tabbed');
});

This adds and removes the tabbed class to the HTML element, which we can then use in our CSS:

:focus {
    outline: 0;
}

.tabbed :focus {
    outline: 2px solid #000;
}

You can try it out on this CodePen.

The benefit of doing this is that you can now make the focus state super obvious. Make it big and contrasty and don't let anyone miss it.

More in posts

Using the :nth-child() CSS pseudo-class

The patterns of :nth-child() can sometimes be tricky to understand. I made a small website to help out.