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

  • By
    How I Stopped WordPress Comment Spam

    I love almost every part of being a tech blogger:  learning, preaching, bantering, researching.  The one part about blogging that I absolutely loathe:  dealing with SPAM comments.  For the past two years, my blog has registered 8,000+ SPAM comments per day.  PER DAY.  Bloating my database...

  • By
    7 Essential JavaScript Functions

    I remember the early days of JavaScript where you needed a simple function for just about everything because the browser vendors implemented features differently, and not just edge features, basic features, like addEventListener and attachEvent.  Times have changed but there are still a few functions each developer should...

Incredible Demos

  • By
    CSS Fixed Positioning

    When you want to keep an element in the same spot in the viewport no matter where on the page the user is, CSS's fixed-positioning functionality is what you need. The CSS Above we set our element 2% from both the top and right hand side of the...

  • By
    HTML5 download Attribute

    I tend to get caught up on the JavaScript side of the HTML5 revolution, and can you blame me?  HTML5 gives us awesome "big" stuff like WebSockets, Web Workers, History, Storage and little helpers like the Element classList collection.  There are, however, smaller features in...

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!