<h1>Touch switch checkbox with css variables</h1>


<div class="wrapper">
  <div id="hammer" class="switch"></div>
</div>
:root {
  --width-bar:100;
  --height-bar:40;
    --horizontal:0;
  --inner:0;
}
body {
  background-color: #F1F1F1
}

.wrapper {
  margin:4em;
  border-radius:2em;
  background-color:rgba(50,50,0,0.15);
  width:calc( var(--width-bar) * 1px);
  height:calc( var(--height-bar) * 1px);
  box-shadow: inset 0 0 0px calc( var(--inner) * 1px ) #00B8C0;
}
.switch {
  background-color:white;
  box-shadow: 0 4px 10px -3px rgba(0,0,0,0.7);
  width:calc( var(--height-bar) * 1.4px);
  height:calc( var(--height-bar) * 1.4px);
  top:0;
  left:calc( var(--height-bar) * -0.1px);
  position:relative;
  border-radius:50%;
      transform: translate3d( calc( var(--horizontal) * 1px ),-15%,0);
    will-change: transform;
    cursor: grab;
    cursor: -moz-grab;
    cursor: -webkit-grab;
}
View Compiled
document.addEventListener("DOMContentLoaded", function() {
  const box = document.querySelector("#hammer");
  const wrapper = document.querySelector(".wrapper");
  const hBox = new Hammer(box);
  hBox.add(new Hammer.Pan({ threshold: 0 }));
  const threshold = 0.4;
  const wrapperWidth = parseInt(getComputedStyle(box).getPropertyValue("--width-bar"));
  const wrapperHeight = parseInt(getComputedStyle(box).getPropertyValue("--height-bar"));
  
  let newX = {
    deltaX: wrapperWidth/3
  };
  let point2 = wrapperWidth - wrapperHeight;
  const physicspoint = { deltaX: 0 };
  const physicspoint2 = { deltaX: point2 };
  let currentPoint = physicspoint;
  
  const whichPoint = function(point,p1,p2) {
    if (newX.deltaX >= (physicspoint.deltaX + physicspoint2.deltaX)/2 ) {
      currentPoint = physicspoint2;
    } else {
      currentPoint = physicspoint;
    }
  }
  const inner = function (a) {
    return (a / point2 * wrapperHeight/2 );
  }

  const springBack = function() {
    dynamics.animate(newX, currentPoint, {
      complete: console.log("complete"),
      change: e => {        
        box.style.setProperty("--horizontal", e.deltaX);
        wrapper.style.setProperty("--inner", inner(e.deltaX));
      },
      type: dynamics.spring
    });
  };

  // listen to events...
  hBox.on("pan", function(e) {
    newX.deltaX = e.deltaX + currentPoint.deltaX;
    if (newX.deltaX > point2 + (point2*threshold)) {
      newX.deltaX = point2 + (point2*threshold);
    }
    if (newX.deltaX < 0 - (point2*threshold) ) {
      newX.deltaX = 0 - (point2*threshold);
    }
    box.style.setProperty("--horizontal",  newX.deltaX);
    wrapper.style.setProperty("--inner",  inner(newX.deltaX) );
  });

  hBox.on("panend", function(e) {
    whichPoint();
    springBack();
  });

  springBack();
});
View Compiled
Run Pen

External CSS

  1. https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta.2/css/bootstrap.css

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/dynamics.js/1.1.5/dynamics.min.js