The :focus-within pseudo-class is a CSS Level 4 selector that is supported by FireFox 52+, Safari 10.1+, iOS Safari 10.3+, Opera 47+ and Chrome 60+. When first writing this piece back in 2017, support for Chrome had just been announced behind a feature flag, but outside of Internet Explorer and Edge, there is little reason to at least play with this selector a bit.

So what does it do, and why is it awesome?

:focus-within is a pseudo-class you add to an existing CSS selector, much like you would with :focus or :hover. The pseudo-class styling kicks in when either the element with :focus-within becomes focused, or a focusable child of that element receives keyboard focus.

Let’s review the following demo and accompanying code. Try keyboard tabbing through the demo:

<div class="my-element">
  <p>A paragraph</p>
  <p>
    <a href="https://scottohara.me">
      My Website
    </a>
  </p>

  <label for="wut_email">
    Your email:
  </label>
  <input type="email" id="wut_email">
</div>
/*
  A crude selector allowing any element 
  that can receive focus within the
  .my-element parent to receive
  a yellow background.
*/
.my-element *:focus {
  background: yellow !important;
  color: #000;
}

/*
  The following :focus-within example
  will NOT style the elements within
  the .my-element selector, like the
  normal :focus above, but will
  style the .my-element container
  when its focusable children
  receive focus.
*/
.my-element:focus-within {
  outline: 3px solid #333;
}

The above .my-element will receive a 3px outline if it programatically receives focus (because <div>s are not meant to receive keyboard focus, without a set tabindex), or if the link or input elements within the <div> receive focus. You can play around with the above basic focus-within demo on codepen.

Focus-within examples

:focus-within is pretty powerful and is not a pseudo-class you would want to add to elements all willy-nilly. Since the pseudo-class activates when any element within it receives focus, it definitely should be used sparingly and likely not on an element that contains many sub-components that also contain focusable child elements.

With that said, there are some common UX interactions that would benefit from :focus-within’s behavior, that were previously reliant on JavaScript to reproduce for keyboard interactions.

Highlighting table rows

One common example: table rows that change background color on hover. Styling like this may be implemented to help sighted users parse complex/long tables, as the visual highlight can make it easier for these user to keep track of the table row they’re currently reading. Unfortunately, without JavaScript, there was no way to do this for sighted keyboard users, until now:

The above example showcases how one can use the :focus-within pseudo-class to highlight an entire table row, if there is at least one focusable element within a table cell of a particular row.

The most important CSS from the table example is the following:

tbody tr:focus-within,
tbody tr:hover {
  background: rgba(lightBlue, .4);
}

But you can view the rest of the table example on codepen.

Support

Likely not a shocker to anyone, but :focus-within still has a ways to go before it can readily be used on projects without any sort of polyfill. This is incredibly important to note as Keith J. Grant’s tweet explains:

At the time of writing, May 2017, here are the browsers that support :focus-within, without needing to turn on experimental flags.

  • FireFox 52+
  • Chrome 60+
  • Desktop Safari 10.1
  • Mobile Safari 10.3

Fortunately, Rodney Rehm has a focus-within polyfill that you can checkout.

You can check out the source code for all of the demos in this article via the listed CodePen and GitHub links below: