Focus Styles on Non-Interactive Elements?

Avatar of Chris Coyier
Chris Coyier on

Last month, Heather Migliorisi looked at the accessibility of Smooth Scrolling. In order to do smooth scrolling, you:

  1. Check if the clicked link is #jump link
  2. Stop the browser default behavior of jumping immediately to that element on the page
  3. Animate the scrolling to the element the #jump link pointed to

Stopping the browser default behavior is the part that is problematic for accessibility. No longer does the #jump link move focus to element the #jump link pointed to. So Heather added a #4: move focus to the element the #jump link pointed to.

But moving focus through JavaScript isn’t possible on every element. Sometimes you need to force that element to be focusable, which she did through setting tabindex="-1".

We since updated our snippet to do this more-accessible handling of focus. Since then, we’ve heard from quite a few folks about a new side effect to the updated snippet:

Notice the glowing blue outline of the headers that were scrolled to.

After the smooth scrolling, the headers that were scrolled to now have the default blue glowing outline that links have by default. Even if we don’t always love the blue glowing outline (the style varies by user agent, it might be a dotted outline, for example) we know better to remove it.

There is even a website dedicated to that sentiment:

http://www.outlinenone.com/

You can change the focus style if you like, but it’s good accessibility to have a distinct focus style for elements that are in focus. I can even imagine an argument for leaving the focus styles alone.

But but but

Headers aren’t focusable elements.

They aren’t “interactive” elements. We aren’t used to seeing focus styles on non-interactive elements. But now, all the sudden, because we used a smooth scrolling technique from the internet, we’re getting them. That tabindex="-1" technique to allow focus is causing it.

I reached out to Heather to ask her about this.

The :focus styling for headings and other non-interactive elements can be removed/left off. It’s really up to the folks behind the creative site if they want it or not there. In some cases, I’ve removed it, in others I’ve styled it. It just depends.

To my surprise, it’s OK to remove focus styles in the case that the element you’re force-focusing isn’t interactive. That last point is important, and Heather clarified:

As long as the headings are not links… ;)

So if you really hated the focus styles, you could do:

h1:focus,
h2:focus, 
h3:focus,
h4:focus,
h5:focus,
h6:focus {
  outline: 0;
}

You’re safe there. Even in the cases of <a><h3></h3></a> or <h3><a></a></h3>, the link still has focus styles.

It’s not just headers

Jump links can point to any element, and there are lots of non-focusable-by-default elements. Another classic technique in this situation is the “yellow fade” technique. Let’s say instead of linking to headers, we were linking to <section>s. When any section comes into focus, we could style it like this:

section:focus {
  outline: 0;
  animation: yellowFade 3s forwards;
}
@keyframes yellowFade {
  from { background: lightYellow; }
  to   { background: white; }
}

Which gives us:

Which is an adaptation of something that was often used for :target.