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
    9 Mind-Blowing Canvas Demos

    The <canvas> element has been a revelation for the visual experts among our ranks.  Canvas provides the means for incredible and efficient animations with the added bonus of no Flash; these developers can flash their awesome JavaScript skills instead.  Here are nine unbelievable canvas demos that...

  • 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...

Incredible Demos

  • By
    Create a Simple News Scroller Using MooTools, Part I:  The Basics

    News scroller have been around forever on the internet. Why? Because they're usually classy and effective. Over the next few weeks, we'll be taking a simple scroller and making it into a flexible, portable class. We have to crawl before we...

  • By
    MooTools Accordion: Mouseover Style

    Everyone loves the MooTools Accordion plugin but I get a lot of requests from readers asking me how to make each accordion item open when the user hovers over the item instead of making the user click. You have two options: hack the original plugin...

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!