Accessible Radio Button Replacements
Using screenreader-only hiding of the original elements they are still keyboard accessible but are visually replaced with content in their wrapper la
by _sir
HTML
<p>
Using screenreader-only hiding of the original elements leaves the radio buttons keyboard accessible but visually replaced with content in their wrapper label, allowing for a clickable, keyboard navigable, and screenreader-friendly interface.
</p>
<form action="" method="POST">
<div class="color-swatches">
<label><input type="radio" name="foo" value="1" class="color sr-only"><div class="swatch" style="background: orange;"></div><div class="labelText">Orange</div></label>
<label><input type="radio" name="foo" value="2" class="color sr-only"><div class="swatch" style="background: black;"></div> <div class="labelText">Black</div></label>
<label><input type="radio" name="foo" value="3" class="color sr-only"><div class="swatch" style="background: red;"></div> <div class="labelText">Red</div></label>
<label><input type="radio" name="foo" value="4" class="color sr-only"><div class="swatch" style="background: green;"></div> <div class="labelText">Green</div></label>
</div>
<input type="text" name="bar" id="bar">
</form>
CSS
.sr-only {
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
}
.color-swatches {
position: relative;
}
.color-swatches label {
display: inline-block;
padding-top: 1.5em;
}
.color-swatches .labelText {
visibility: hidden;
position: absolute;
top: 0;
left: 0;
}
div.swatch {
width: 20px;
height: 20px;
border: 1px solid gray;
margin: 5px;
}
input:checked + div.swatch {
border: 1px solid white;
outline: 2px solid gray;
}
input:checked ~ .labelText {
visibility: visible !important;
}
/*
* Native Focus Mimic logic from
* https://ghinda.net/article/mimic-native-focus-css/
*/
input:focus + div.swatch {
border: 1px solid white;
outline-width: 2px;
outline-style: solid;
outline-color: Highlight;
}
@media (-webkit-min-device-pixel-ratio:0) {
input:focus + div.swatch {
outline-color: -webkit-focus-ring-color;
outline-style: auto;
}
}
JavaScript
$('input').on('click', function() {
$('#bar').val(this.value);
});