CSS :focus-within

By  on  

Using :hover to display additional information or elements is a very useful technique but a big drawback to using the hover pseudo-class is that they are usually not accessibility-friendly. Not everyone uses a mouse and some users have visual impairments, so they rely on screen readers or the keyboard -- two functionality that don't technically hover.

Luckily the CSS spec gives us a gift to pair with :hover: :focus-within. With :focus-within developers can modify styles of elements when an element or its children has keyboard focus!

Consider the following HTML template with default CSS styling:

<ul id="sports">
  <li>
    <label>
      <input type="checkbox" name="sports[]">
      Soccer
      <button class="remove">Remove</button>
    </label>
    <!-- ... -->
  </li>
</ul>
#sports .remove {
  display: none;
}

#sports li:hover .remove {
  display: inline-block;
}

With the code above, hovering over a list item would show the "remove" button. That's great for mouse users but totally useless for keyboard users. Let's fix that using :focus-within:

#sports .remove {
  display: none;
}

#sports li:hover .remove,
#sports li:focus-within .remove {
  display: inline-block;
}

Once focus hits the checkbox, the focus is technically within the list item and thus we can employ :focus-within to show the "remove" button.

Accessibility is something that gets considered last but shouldn't be an afterthought; in a way, :focus-within is a useful ally even when accessibility was an afterthought. Even when considering accessibility up front, :focus-within should be in every developer's toolbox!

Recent Features

Incredible Demos

  • By
    Highlighter: A MooTools Search &#038; Highlight Plugin

    Searching within the page is a major browser functionality, but what if we could code a search box in JavaScript that would do the same thing? I set out to do that using MooTools and ended up with a pretty decent solution. The MooTools JavaScript Class The...

  • By
    Create a Simple Slideshow Using MooTools

    One excellent way to add dynamism to any website is to implement a slideshow featuring images or sliding content. Of course there are numerous slideshow plugins available but many of them can be overkill if you want to do simple slideshow without controls or events.

Discussion

  1. I think there’s a missing :hover part of your demonstration above. The remove button will never show on hover as the code is currently written.

    I love demo’s – so I put one together here:
    https://codepen.io/aaronsaray/pen/mZMwRo

  2. The second declaration in this selector:

    #sports li:hover .remove,
    #sports li:focus-within .remove {
      display: inline-block;
    }
    

    …will cause the hover (the one it does support) to not work at all in Internet Explorer 11 — a browser still used by many folks who rely on JAWS or cannot afford new equipment or are trapped in old locked-down corporate environments.

    May be best to split those up into two declarations and perhaps script a thing for IE11 that puts a class (maybe named focus-within) on the container:

    #sports li:hover .remove,
    #sports li.focus-within .remove {
      display: inline-block;
    }
    
    #sports li:focus-within .remove {
      display: inline-block;
    }
    
  3. Maria Blair

    It’s a great CSS rule, thank you for sharing it, but unfortunately it’s not supported in EI or Edge… or many other mobile browsers: https://caniuse.com/#search=%3Afocus-within
    I usually combine my :hover rules with :focus.

  4. That’s pretty cool! It’s a shame that IE11 and even some version of Edge don’t support this – it’s really helpful. I had never heard of it before.

  5. Brandon

    Hi!
    I’m going to be using focus-within to address some accessibility concerns. In order to support IE11, I’m going to try this polyfill: https://www.npmjs.com/package/focus-within-polyfill

    Thank you for your article!

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!