'Make custom checkbox switch Label element a11y tab / keyboard accessible
So I'm trying to make custom slider that's cross browser (IE11, Chrome, Firefox, Edge) that's also a11y accessible and I'm having trouble getting the label element to respond to space bar for selection like a natural checkbox. I can do it easily with code of course but was curious if there's maybe something I'm missing with just the html/css I could do to accomplish the same thing.
As example see below, tabindex
of course provides the visual and tabbing, but I can't seem to get the label to toggle it like a click would on label
element. Should I just go the easy route and let some code handle it or does someone want to teach me something? Cheers!
// not yet, and yes I know I haven't added the aria attributes etc, it's just a quick PoC :)
main {
display: block;
margin: 0 auto;
padding: 2rem;
width: auto;
}
.slide-toggle {
margin: 0 3rem;
display: inline-block;
}
.slide-toggle:last-of-type {
margin-left: 0;
}
.slide-toggle input {
display: none;
}
.slide-toggle input:checked ~ label {
color: #fff;
background-color: skyblue;
}
.slide-toggle input:checked ~ label:after {
transform: translateX(100%);
}
.slide-toggle label {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
position: relative;
padding: .25rem 0;
cursor: pointer;
user-select: none;
border: #bbb 1px solid;
border-radius: 3px;
}
.slide-toggle label:after {
display: block;
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 45%;
margin: .25rem;
border: #bbb 1px solid;
border-radius: 3px;
background-color: #ddd;
transition: transform 0.25s cubic-bezier(0.6, 0.82, 0, 0.76);
}
.slide-toggle label:focus {
box-shadow: 0 0 0 8px red;
}
.slide-toggle label:hover {
border-color: #777;
}
.slide-toggle label div {
flex-grow: 1;
flex-basis: 50%;
flex-wrap: nowrap;
text-align: center;
min-width: 1rem;
margin: .25rem 1rem;
}
<link href="https://use.fontawesome.com/releases/v5.8.2/css/all.css" rel="stylesheet"/>
<main>
<h2>Please click a slide toggle for example;</h2>
<div class="slide-toggle">
<input id="guidLater"
type="checkbox"/>
<label for="guidLater"
tabindex="0"
role="checkbox">
<div>YES</div>
<div>NO</div>
</label>
</div>
No Translation Option:
<div class="slide-toggle">
<input id="guidLater4"
type="checkbox"/>
<label for="guidLater4"
tabindex="0"
role="checkbox">
<div><i class="fas fa-check" style="color:green"></i></div>
<div><i class="fas fa-times" style="color:red;"></i></div>
</label>
</div>
</main>
Solution 1:[1]
Without getting too far into the specifics, as there are many, I'll just attack this from a pure solution perspective and provide some insight.
With HTML5 elements, the idea is that they have functionality assigned to them by default. For example, a checkbox inherits the behaviors that a checkbox should have because it's a default element. You also shouldn't be re-purposing elements for other uses if native ones are available as this breaks the first two rules of ARIA.
If you can use a native HTML element [HTML51] or attribute with the semantics and behavior you require already built in, instead of re-purposing an element and adding an ARIA role, state or property to make it accessible, then do so.
And
Do not change native semantics, unless you really have to.
The input types of Range (a slider) and Checkbox have two vastly different sets of keyboard behaviors, so i'm not surprised that this isn't working correctly.
Solution 2:[2]
I think what you mean to create is a "switch"
You shouldn't have display: none
on the actual checkbox
. You need to visually hide it, but still have it on the page because only then it would catch the space key press.
An easy (& suggested) way to do that is
.slide-toggle input {
width: 0;
height: 0;
}
also you don't need to have role="checkbox"
and tabindex
on the label.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Paolo F |
Solution 2 | gaurav5430 |