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
    Send Text Messages with PHP

    Kids these days, I tell ya.  All they care about is the technology.  The video games.  The bottled water.  Oh, and the texting, always the texting.  Back in my day, all we had was...OK, I had all of these things too.  But I still don't get...

  • By
    Responsive and Infinitely Scalable JS Animations

    Back in late 2012 it was not easy to find open source projects using requestAnimationFrame() - this is the hook that allows Javascript code to synchronize with a web browser's native paint loop. Animations using this method can run at 60 fps and deliver fantastic...

Incredible Demos

  • By
    MooTools ASCII Art

    I didn't realize that I truly was a nerd until I could admit to myself that ASCII art was better than the pieces Picasso, Monet, or Van Gogh could create.  ASCII art is unmatched in its beauty, simplicity, and ... OK, well, I'm being ridiculous;  ASCII...

  • By
    dwImageProtector Plugin for jQuery

    I've always been curious about the jQuery JavaScript library. jQuery has captured the hearts of web designers and developers everywhere and I've always wondered why. I've been told it's easy, which is probably why designers were so quick to adopt it NOT that designers...

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!