Skip to content

Instantly share code, notes, and snippets.

@TemporaryJam
Created May 16, 2019 23:24
Show Gist options
  • Save TemporaryJam/8fad6deab2d8acd442a4599249374583 to your computer and use it in GitHub Desktop.
Save TemporaryJam/8fad6deab2d8acd442a4599249374583 to your computer and use it in GitHub Desktop.
Accessible custom styled radios and checkboxes - 100% CSS IE10+
<!DOCTYPE html>
<head>
<title>A11y radios</title>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<style>
.section input[type="radio"],
.section input[type="checkbox"]{
}
.checkbox_wrapper {
margin-bottom: 15px;
}
.checkbox_wrapper label {
position: relative;
padding-left: 25px;
}
.checkbox_wrapper input[type="checkbox"],
.checkbox_wrapper input[type="radio"] {
position: relative;
left: 7px;
}
.checkbox_wrapper span::before,
.checkbox_wrapper span::after {
content: '';
position: absolute;
top: 0;
bottom: 0;
margin: auto;
}
.checkbox_wrapper span.radio,
.checkbox_wrapper span.checkbox {
min-height: 1em;
min-width: 1px;
display: inline-block;
}
.checkbox_wrapper span.radio:hover,
.checkbox_wrapper span.checkbox:hover {
cursor: pointer;
}
.checkbox_wrapper span.radio::before {
left: -16px;
width: 30px;
height: 30px;
background-color: #A8AAC1;
border-radius: 15px;
}
.checkbox_wrapper span.radio::after {
left: -12px;
width: 22px;
height: 22px;
border-radius: 12px;
background-color: #33597d;
transition: background-color .25s;
display: none;
}
input[type="radio"]:checked + label span.radio::after {
display: block;
}
input[type="radio"]:focus + label span.radio:before,
input[type="checkbox"]:focus + label span.checkbox:before {
-webkit-box-shadow: 0px 0px 5px 2px rgba(103,174,235,1);
-moz-box-shadow: 0px 0px 5px 2px rgba(103,174,235,1);
box-shadow: 0px 0px 5px 2px rgba(103,174,235,1);
}
/** Checkboxes */
.checkbox_wrapper span.checkbox::before {
width: 27px;
height: 27px;
background-color: #fff;
left: -18px;
box-sizing: border-box;
border: 2px solid #A8AAC1;
border-radius: 3px;
transition: border-color .2s;
}
.checkbox_wrapper span.checkbox:hover::before {
/*border: 3px solid #F0FF76;*/
}
.checkbox_wrapper span.checkbox::after {
left: -13px;
top: 1px;
content: '\f00c';
font-family: 'FontAwesome';
color: transparent;
transition: color .2s;
}
input[type="checkbox"]:checked + label span.checkbox::after {
color: #33597d;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-12 mb-5">
<h1>Accessible custom checkboxes and radios</h1>
</div>
<div class="col-6">
<h2 class="mb-5">Radios</h2>
<section id="first" class="section">
<div class="checkbox_wrapper">
<input type="radio" name="group1" id="radio-1">
<label for="radio-1"><span class="radio">1<sup>st</sup> December</span></label>
</div>
<div class="checkbox_wrapper">
<input type="radio" name="group1" id="radio-2">
<label for="radio-2"><span class="radio">8<sup>th</sup> December</span></label>
</div>
<div class="checkbox_wrapper">
<input type="radio" name="group1" id="radio-3">
<label for="radio-3"><span class="radio">22<sup>nd</sup> December</span></label>
</div>
</section>
<div>
<h3 class="mb-2">States</h3>
Radio 1: <span id="radio1state">unselected</span><br>
Radio 2: <span id="radio2state">unselected</span><br>
Radio 3: <span id="radio3state">unselected</span>
</div>
</div>
<!------- CHECKBOXES --------->
<div class="col-6">
<h2 class="mb-5">Checkboxes</h2>
<section id="second" class="section">
<div class="checkbox_wrapper">
<input type="checkbox" name="group2" id="checkbox-1">
<label for="checkbox-1"><span class="checkbox">1<sup>st</sup> December</span></label>
</div>
<div class="checkbox_wrapper">
<input type="checkbox" name="group2" id="checkbox-2">
<label for="checkbox-2"><span class="checkbox">8<sup>th</sup> December</span></label>
</div>
<div class="checkbox_wrapper">
<input type="checkbox" name="group2" id="checkbox-3">
<label for="checkbox-3"><span class="checkbox">22<sup>nd</sup> December</span></label>
</div>
</section>
<div>
<h3 class="mb-2">States</h3>
Checkbox 1: <span id="checkbox1state">unchecked</span><br>
Checkbox 2: <span id="checkbox2state">unchecked</span><br>
Checkbox 3: <span id="checkbox3state">unchecked</span>
</div>
</div>
</div>
</div>
<hr>
<!-- DEMO TABLE BASED STRUCTURE -->
<div style="display: none">
<table>
<tr>
<td>
<div class="checkbox_wrapper"> <!-- .checkbox_wrapper is used to target the replaced checkbox/radio styles -->
<input type="checkbox" name="CHECKBOX_GROUP_NAME[]" id="CHECKBOX_UNIQUE_ID">
<label for="CHECKBOX_UNIQUE_ID" class="pl-2">
<!--
This set of span elements is to provide
- positioning for the custom presentation elements via :before & :after
- provide a home for the 'wordy' accessible label for the option. If no 'wordy' accessible
version has been provided it should fallback to hold the standard option text. This element
structure must remain intact regardless.
-->
<span class="checkbox"> <!-- provides positioning for :before & :after elements -->
<span class="sr-only">the first of December <!-- Wordy accessible text --></span>
</span>
</label>
</div>
</td>
<td>
<!-- Inputs can have multiple <labels>, this allows us to maintain the existing table layout -->
<!-- This label contains the standard option text only, wrapped within the aria-hidden span -->
<label for="CHECKBOX_UNIQUE_ID">
<!-- The additional span with aria-hidden is because you can't hide a label from a screen reader
and it'll read out the label twice. But, you can hide elements within a label -->
<span aria-hidden="true">1<sup>st</sup> December</span>
</label>
</td>
</tr>
</table>
</div>
<!-- END DEMO -->
<div class="container">
<div class="row">
<div class="col-12">
<h1 class="mb-5">Accessible custom checkboxes and radios in tables</h1>
</div>
<div class="col-6">
<table>
<tr>
<td>
<div class="checkbox_wrapper">
<input type="radio" name="group3" id="radio-4">
<label for="radio-4"><span class="radio"><span class="sr-only">the first of December</span></span></label>
</div>
</td>
<td>
<label for="radio-4"><span aria-hidden="true">1<sup>st</sup> December</span></label>
</td>
</tr>
<tr>
<td>
<div class="checkbox_wrapper">
<input type="radio" name="group3" id="radio-5">
<label for="radio-5"><span class="radio"><span class="sr-only">the eighth of December</span></span></label>
</div>
</td>
<td aria-hidden="true">
<label for="radio-5"><span aria-hidden="true">8<sup>th</sup> December</span></label>
</td>
</tr>
<tr>
<td>
<div class="checkbox_wrapper">
<input type="radio" name="group3" id="radio-6">
<label for="radio-6"><span class="radio"><span class="sr-only">The twenty second of December</span></span></label>
</div>
</td>
<td aria-hidden="true">
<label for="radio-6"><span aria-hidden="true">22<sup>nd</sup> December</span></label>
</td>
</tr>
</table>
<div>
<h3 class="mb-2">States</h3>
Radio 4: <span id="radio4state">unselected</span><br>
Radio 5: <span id="radio5state">unselected</span><br>
Radio 6: <span id="radio6state">unselected</span>
</div>
</div>
<div class="col-6">
<table>
<tr>
<td>
<div class="checkbox_wrapper">
<input type="checkbox" name="group4" id="checkbox-4">
<label for="checkbox-4" class="pl-2"><span class="checkbox"><span class="sr-only">the first of December</span></span></label>
</div>
</td>
<td>
<label for="checkbox-4"><span aria-hidden="true">1<sup>st</sup> December</span></label>
</td>
</tr>
<tr>
<td>
<div class="checkbox_wrapper">
<input type="checkbox" name="group4" id="checkbox-5">
<label for="checkbox-5" class="pl-2"><span class="checkbox"><span class="sr-only">the eighth of December</span></span></label>
</div>
</td>
<td>
<label for="checkbox-5"><span aria-hidden="true">8<sup>th</sup> December</span></label>
</td>
</tr>
<tr>
<td>
<div class="checkbox_wrapper">
<input type="checkbox" name="group4" id="checkbox-6">
<label for="checkbox-6" class="pl-2"><span class="checkbox"><span class="sr-only">The twenty second of December</span></span></label>
</div>
</td>
<td>
<label for="checkbox-6"><span aria-hidden="true">22<sup>nd</sup> December</span></label>
</td>
</tr>
</table>
<div>
<h3 class="mb-2">States</h3>
Checkbox 4: <span id="checkbox4state">unchecked</span><br>
Checkbox 5: <span id="checkbox5state">unchecked</span><br>
Checkbox 6: <span id="checkbox6state">unchecked</span>
</div>
</div>
</div>
</div>
<script>
function updateStates() {
if ($('#radio-1').prop('checked')) { $('#radio1state').text('selected'); } else { $('#radio1state').text('unselected') }
if ($('#radio-2').prop('checked')) { $('#radio2state').text('selected'); } else { $('#radio2state').text('unselected') }
if ($('#radio-3').prop('checked')) { $('#radio3state').text('selected'); } else { $('#radio3state').text('unselected') }
if ($('#radio-4').prop('checked')) { $('#radio4state').text('selected'); } else { $('#radio4state').text('unselected') }
if ($('#radio-5').prop('checked')) { $('#radio5state').text('selected'); } else { $('#radio5state').text('unselected') }
if ($('#radio-6').prop('checked')) { $('#radio6state').text('selected'); } else { $('#radio6state').text('unselected') }
//Checkboxes
if ($('#checkbox-1').prop('checked')) { $('#checkbox1state').text('checked'); } else { $('#checkbox1state').text('unchecked') }
if ($('#checkbox-2').prop('checked')) { $('#checkbox2state').text('checked'); } else { $('#checkbox2state').text('unchecked') }
if ($('#checkbox-3').prop('checked')) { $('#checkbox3state').text('checked'); } else { $('#checkbox3state').text('unchecked') }
//Table checkboxes
if ($('#checkbox-4').prop('checked')) { $('#checkbox4state').text('checked'); } else { $('#checkbox4state').text('unchecked') }
if ($('#checkbox-5').prop('checked')) { $('#checkbox5state').text('checked'); } else { $('#checkbox5state').text('unchecked') }
if ($('#checkbox-6').prop('checked')) { $('#checkbox6state').text('checked'); } else { $('#checkbox6state').text('unchecked') }
}
window.setInterval(updateStates, 300);
$(document).ready(function() {
$('#make_clickable').click(function(e) {
$(e.target).css('color','red');
});
$('#make_clickable').keyup(function(e) {
$(e.target).css('color','blue');
});
})
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment