In an HTML form (being generated by React, but that’s not relevant), I have a checkbox with a label. The checkbox is hidden (invisible), and the way to check/uncheck it is by clicking the label. At the moment, I have the tabindex set so that the label comes into focus after the previous form control. However, I can’t find a way to let the user check/uncheck the checkbox using only the keyboard, even though the label is in focus. Does anyone have any idea how to do this? Basically I want there to be a way to achieve using only the keyboard what would usually be done by clicking the label with your mouse – checking/unchecking the checkbox.
Here is the basic idea of the code I’m using:
Note: I’ve added a small js snippet to log the state of the checkbox to the console whenever the checkbox is changed.
document.getElementById("hidden-checkbox").onchange = function () {
console.log(document.getElementById("hidden-checkbox").checked);
}
#hidden-checkbox {
display: none;
/* Could also use:
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
padding: 0;
border: 0;
height: 1px;
width: 1px;
overflow: hidden;
*/
}
<div class="fields">
<input type="text" id="other-field" tabindex="1">
<input type="text" id="other-field-2" tabindex="2">
<input type="checkbox" id="hidden-checkbox" tabindex="-1">
<label id="label" for="hidden-checkbox" tabindex="3">Click this to toggle!</label>
</div>
2
Answers
You could keep going as you did with your concept of removing the actual checkbox from tab order and make the label focusable at its place, but be aware that:
However, you you could do much simpler by letting the checkbox be normally focusable. Spacebar and enter will work without the need for you to do anything special.
Screen reader users will find it and will be able to check it as usual. To them, it will just "look" like a normal checkbox. No ARIA is needed.
Since the actual checkbox is invisible on the screen, you can use some CSS or js to indicate the checked state to the user and when it has the focus.
You are certainly already doing it at least for the state, so it shouldn’t be a big deal.
You don’t need to fuss around with
tabIndex
or anything. When a label is associated with a checkbox, mouse clicking on the label is the same as clicking on the checkbox. How do you still make the checkbox available to keyboard-only and screen reader users, even after you hide it? By hiding it visually.If you make the checkbox have a height/width of 0, it won’t appear visually, but is still available when you tab around or look for checkboxes. Like this:
If you want to see it in action, here’s a pure CSS solution:
https://codepen.io/chart2music/pen/OJojagX
Side note –
Your use case doesn’t need
tabIndex
at all, anywhere. Input fields will receive tab focus automatically, so not only do you not need to add the tabIndex attribute, you’re likely to create a weird and unpredictable tab order. Here’s your rule of thumb for when to use it:tabIndex=-1
tabIndex=0