CSS :focus-within
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!
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
Does this work for you? https://codepen.io/simevidas/pen/qzXXME?editors=0100
Hey – there you go – even better! I don’t know what I was thinking having two separate declarations and mixing my inline+inline-block. Didn’t have my coffee yet apparently.
The second declaration in this selector:
…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: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.
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.
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!