<p>This is a toggle that overrides a native HTML checkbox input element.</p>
<div class="toggle-switch" tabindex="0">
<input type="checkbox" name="my_checkbox" value="yes" id="checkbox-id" />
<label for="checkbox-id">
<div class="area" aria-hidden="true">
<div class="background">
<div class="handle"></div>
</div>
</div>
A text label
</label>
</div>
<p>The toggle is hidden from accessibility tools, such as screen readers, which will use the native HTML checkbox. Keyboard users can tab to the element and toggle it with the <kbd>SPACE</kbd> key.</p>
.toggle-switch {
--width: 30px;
--height: 20px;
--padding: 2px;
--handle-size: calc(var(--height) - var(--padding) * 2);
display: inline-block;
outline-width: 0;
}
.toggle-switch > input {
position: absolute;
clip: rect(1px, 1px, 1px, 1px);
clip-path: inset(50%);
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
}
label {
display: inline-grid;
grid-template-columns: auto auto;
column-gap: 10px;
}
.area {
padding: 4px;
margin: -4px;
}
.toggle-switch :active {
outline-width: 0;
}
.background,
.handle {
transition: all 0.1s ease;
}
.background {
display: inline-flex;
flex-direction: row;
align-items: center;
width: var(--width);
height: var(--height);
border-radius: var(--height);
padding: 0 var(--padding);
vertical-align: text-bottom;
user-select: none;
background-color: darkgray;
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.25);
overflow: hidden;
transition: background-color .15s ease;
}
.toggle-switch:focus .area {
outline: 1px dotted gray;
}
.toggle-switch:active .area {
outline-width: 0;
}
.toggle-switch:focus .background,
.area:hover .background {
background-color: gray;
}
.handle {
width: var(--handle-size);
height: var(--handle-size);
background-color: white;
border-radius: 50%;
box-shadow:
0 2px 4px rgba(0, 0, 0, 0.5),
inset 0 2px 4px rgba(0, 0, 0, 0.15);
}
.handle:hover {
background-color: white;
}
input:checked + label .area .background {
background-color: lightgreen;
}
input:checked + label .area .handle {
background-color: white;
transform: translateX(calc(var(--width) - var(--handle-size)));
}
/**
* Styles for Codepen.
*/
body {
font-family: sans-serif;
color: #3f3f3f;
max-width: 480px;
margin: 20px auto;
padding: 0 20px;
line-height: 1.35;
}
@media (min-width: 640px) {
body {
margin-top: 40px;
}
}
View Compiled
const $ = selector => [document.querySelectorAll(selector)];
const onKeyPress = ( { key, target }) => {
if (key !== " ") return;
const element = target.querySelector('input');
element.checked = !element.checked;
};
$(".toggle-switch").forEach(element => {
element.addEventListener("keypress", onKeyPress);
});
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.