Reputation: 1926
Clicking on an input label within a parent element with :focus-within
styles causes an undesirable flash of the :focus-within
styles.
I wanted to use :focus-within
to improve accessibility by providing the user with some visual feedback when a group of related radio-buttons is in focus.
Attaching labels to the radio buttons allows the user to click a label to select the corresponding radio button. However, clicking the label causes the :focus-within
styles to flash off while the mouse is down.
<div class="parent">
<label><input type="radio" name="x"/>First</label>
<label><input type="radio" name="x"/>Second</label>
<label><input type="radio" name="x"/>Third</label>
</div>
.parent {
border: 2px solid grey;
padding: 10px;
&:focus-within {
background: skyblue;
}
}
https://jsfiddle.net/ggamir/nb3sy26k/
Upvotes: 3
Views: 1778
Reputation: 1926
Add tabindex="-1"
to the labels. This allows them to become "focusable" elements without being part of the tabindex order.
https://jsfiddle.net/ggamir/krnavadz/
When a user begins clicking on a label (mousedown
), the previously focused radio button loses its :focus
state.
When the user completes the click (mouseup
) on a label, the browser selects the corresponding radio button and gives it a:focus
state.
By default, the label
element is "unfocusable", so while the mouse is down on the label, nothing in the parent has focus, which is why the :focus-within
styles are removed for that moment.
Adding tabindex
to the label makes it a "focusable" element, so while the mouse clicks down on it, the parent still has :focus-within
, so the styles will remain applied throughout the whole duration of the click.
Using -1
in tabindex="-1"
is important so that the label doesn't unnecessarily get added into the tabindex order.
There are some default :focus
and :active
styles for elements which will be applied to the label once it is made "focusable" through tabindex
, so clearing those may be desired so as to not confuse the user:
.my-label:focus, .my-label:active {
outline: none;
}
Upvotes: 3