Naturalized Checkbox Toggle Switches

This demo is a response to a post by Marcus Connor addressing confusion with checkbox toggle switches. It’s an attempt to make them work more like switches. Drag the handles back and forth and see the checkbox state change. Developed using html, css and JavaScript. Demo and download available.

Demo Download

Author Jon Kantner
Hits
Created NOVEMBER 13, 2018
License Open
Compatible browsers Chrome, Firefox, Safari

HTML Snippet

<form>
	State: <input id="toggle1" class="ti" type="checkbox" name="dummy"><label for="toggle1" class="t"><span class="t-handle"></span><span class="t-shade"></span></label>
	State: <input id="toggle2" class="ti" type="checkbox" name="dummy"><label for="toggle2" class="t"><span class="t-handle"></span><span class="t-shade"></span></label>
</form>

CSS Code

*, *:before, *:after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  font-size: calc(18px + (27 - 18) * (100vw - 320px)/(1600 - 320));
}

body, input {
  color: #2e2e2e;
  font: 1em "Hind", Helvetica, sans-serif;
  line-height: 1.5;
}

body {
  background: #ddd;
}

form {
  padding: 1.5em;
}

p {
  margin-bottom: 1.5em;
}

.t {
  cursor: pointer;
  font-size: 1.5em;
  margin: 0.75em 0;
  position: relative;
  width: 3em;
  height: 1.5em;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.t, .t .t-handle, .t .t-shade {
  display: block;
  border-radius: 0.75em;
}
.t, .t .t-handle {
  background: #fff;
}
.t .t-handle, .t .t-shade {
  top: 0;
  left: 0;
  position: absolute;
  transition: all 0.15s linear;
  width: 1.5em;
  height: 1.5em;
}
.t .t-handle {
  box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.3);
  z-index: 1;
}
.t .t-shade {
  background: #5785f6;
}
.t:active .t-handle {
  width: 1.75em;
}

.ti {
  vertical-align: middle;
}
.ti:checked + .t .t-handle {
  left: calc(100% - 1.5em);
}
.ti:checked + .t .t-shade {
  width: 3em;
}
.ti:checked + .t:active .t-handle {
  left: calc(100% - 1.75em);
}

JavaScript

window.addEventListener("DOMContentLoaded",toggles);
function toggles() {
	var tHandles = document.querySelectorAll(".t-handle"),
		isDown = false,
		isAtEdge = false,
		eX = 0,
		down = function(e) {
			isDown = true;
			let parent = this.parentNode;
			eX = e.pageX - parent.offsetLeft;
		},
		move = function(e) {
			if (isDown) {
				let parent = this.parentNode;
			    eX = e.pageX - parent.offsetLeft;
				
				// keep within movable room
				if (eX > parent.offsetWidth / 4 && eX < parent.offsetWidth - this.offsetWidth / 2) {
					this.style.left = (eX - parent.offsetWidth / 4) + "px";
					this.nextSibling.style.width = (parent.offsetWidth / 2) + (eX - parent.offsetWidth / 4) + "px";
		            isAtEdge = false;
					
				// at left edge
				} else if (eX < parent.offsetWidth / 4) {
					parent.previousSibling.checked = false;
		            isAtEdge = true;
					
				// at right edge
				} else if (eX > parent.offsetWidth - this.offsetWidth / 2) {
					parent.previousSibling.checked = true;
		            isAtEdge = true;
				}
			}
		},
		up = function(e) {
			isDown = false;
			let parent = this.parentNode;
			this.style = "";
			this.nextSibling.style = "";
			
		},
		stopCheckUndo = function(e) {
			// prevent reverting of state after hitting edge
			if (isAtEdge) {
				isAtEdge = false;
				e.preventDefault();
		        return false;
			}
		};
	
	// add functions to switches
	var isMobile = "ontouchstart" in document.documentElement;
	for (var t in tHandles) {
		if (+t < tHandles.length) {
			tHandles[t].parentNode.addEventListener("click",stopCheckUndo);
			tHandles[t].addEventListener(isMobile ? "touchstart" : "mousedown",down);
			tHandles[t].addEventListener(isMobile ? "touchend" : "mouseup",up);
			tHandles[t].addEventListener(isMobile ? "touchmove" : "mousemove",move);
			tHandles[t].addEventListener(isMobile ? "touchleave" : "mouseout", up);
		}
	}
}

Preview

Naturalized Checkbox Toggle Switches Preview

Advertisement

Google Matched Content...