Focus Styles Only on Tab Not Click

Focus styles are great for accessibility, making it clear which element is currently responsive to keyboard events. However, as focus is also changed via mouse click, focus styles apply to elements after they have been clicked. This makes less sense than for keyboard navigation and can detract from the aesthetics of the application for those with no visual impairment. In this post I present a method to apply focus styles only via keyboard and not mouse. The aim is to maintain accessibility when required and keep the aesthetic clean when possible.

The :focus-visible pseudo-class natively supports this behaviour without JavaScript and should be the preferred solution where browser support allows.

Implementation

The way to do this is to blur the focus using a focus event listener. We need a way to determine in the listener if the focus was triggered via mouse or keyboard. As mousedown events are fired before focus events we can set a flag on mousedown to indicate a mouse action is occurring. We can later reset this flag on mouseup. When a focus event occurs we only blur focus if the event was triggered by the mouse.

let mouseDown = false;

element.addEventListener('mousedown', () => {
  mouseDown = true;
});

element.addEventListener('mouseup', () => {
  mouseDown = false;
});

element.addEventListener('focus', (event) => {
  if (mouseDown) {
    event.target.blur();
  }
});

Demo

The following example shows this technique in action. It features a focusable div which changes colour in response to clicks and the enter key.

When the checkbox is checked the listeners are added to the box. When it is unchecked they are removed.

First, try navigating focus to the square with the keyboard and observe the focus style. Then navigate back off and on with the mouse — you should see the same focus style.

Next, enable the checkbox and repeat the same steps. Now you should only see the focus style when navigating via keyboard.

Conclusion

This is a simple technique but is great for keeping your interface clean for mouse users when required. It is particularly suitable for interactive SVGs where adding focus styles might not gel well with the image. An example of this can be seen on my project Greta's Poetry where the poems each have favourite checkboxes with SVG backgrounds.

Tags: Web, CSS, JavaScript