min read

Accessible disappearing header thanks to :focus-within

So, in a side project I'm working on I wanted to make it so that the navbar would disappear when not in use. So I made it so that it has opacity: 0 by default. If you click in the middle of the viewport it becomes opacity: 1. After a few seconds it hides itself again.

You can check out a demo below. Just click anywhere within the content of the box:

Click here to see the nav.

It's a nice effect and works exactly how I wanted... Except there's one problem. If you use the keyboard and tab into the navbar in order to use one of the buttons it remains invisible. Try it above. You can tab into the button but won't see that the button is focused. 😔

At first I thought of these two possible solutions:

  1. Give the navbar a tabindex which makes it focusable. Then I could use the :focus selector to make it visible. However this only works when the navbar itself is focused; once you tab to one of the button it loses focus and would disappear. So this one was a fail.
  2. Write some JavaScript to listen to when the navbar receives focus and add a class. Remove the class when it loses focus. This would have of course worked but it would also make me cry. fail.

:focus-within

And then somehow :focus-within crawled into my mind. I have never used this selector before, I only read about it... somewhere. It does make you wonder how developers who don't read material or try to "stay in the know" find out about things like this. Because I was dangerously close to going the JavaScript route.

Anyways, the solution is dead simple. The :focus-within selector can be used to select elements which are ancestors of elements with focus. This means in my case if any of the buttons have focus, I can give the navbar a opacity: 1. Here's the diff of the change:

  .demo-header.open,
+ .demo-header:focus-within {
    opacity: 1;
  }

And another demo. This time try to tab in. Notice that the focus goes to the buttons, and once you tab out it disappears again. Perfect!

Click here to see the nav. Or tab into it!