Accessible css / js switch

by ian_smithz

HTML

<link rel="stylesheet" href="https://www.screwfix.com/assets/css/sfx.min.css">
<br> <br>

<label class="check-switch" for="switch_1">
  <input id="switch_1" type="checkbox">
  <span aria-hidden="true"></span>
</label>

<!-- Some screen reader combinations reported to be buggy with role="switch" - you can just use checkbox version -->
<!--
<label class="check-switch" for="switch_2">

  <input id="switch_2" data-check-switch="" role="switch" type="checkbox">
  <span aria-hidden="true"></span>
</label>
-->

CSS

/* containing label */
.check-switch {
	padding: .5em;
  margin: 0 3em;
	position: relative;
}



/* using the before/after pseudo elements of the span to create the "switch" */
.check-switch span:before,
.check-switch span:after {
	border: 1px solid #565656;
	content: "";
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
}

/* styling specific to the knob of the switch */
.check-switch span:after {
	background: #fff;
	border-radius: 100%;
	height: 1.5em;
	right: 1.5em;
	transition: right .1825s ease-in-out;
	width: 1.5em;
}

/* styling specific to the knob "container" */
.check-switch span:before {
	background: #eee;
	border-radius: 1.75em;
	height: 1.75em;
	right: .25em;
	transition: background .2s ease-in-out;
	width: 2.75em;
}

/* hide the actual checkbox from view, but not from keyboards or ATs.
   Instead of standard visually hidden styling, instead set opacity to
   almost 0 (not zero for ChomeVox legacy bug), pointer-events none, and
   then set to full height/width of container element so that VO focus
   ring outlines the component, instead of a tiny box within the component
*/
.check-switch input {
	height: 100%;
	left: 0;
	opacity: .0001;
	position: absolute;
	top: 0;
	width: 100%;
}

.check-switch input:not([role="button"]) {
	pointer-events: none;
}

.check-switch input:focus + span:before {
	  /*outline: #a9a9a9 dotted 2px;
    outline-offset: 1px;*/
    outline: 0;
    -webkit-box-shadow: 0 0 0 2px rgba(2,117,216,.25);
    box-shadow: 0 0 0 2px rgba(2,117,216,.25);
}

/* change the position of the knob to indicate it has been checked*/
.check-switch input:checked + span:after {
	right: .25em;
}

/* update the color of the "container" to further visually indicate state */
.check-switch input:checked + span:before {
	background: #2196f3;
}

/* 'color in' the switch knob in high contrast mode by giving it
   a large border */
@media screen and (-ms-high-contrast: active) {
	.check-switch span:after {
		background-color: windowText;
	}
}