JSFiddle - React, Tailwind, and code Playground
by nukeboy212
HTML
<input type="range" multiple value="10,40, 90" />
CSS
@supports (--css: variables) {
input[type="range"].multirange {
-webkit-appearance: none;
padding: 0;
margin: 0;
display: inline-block;
vertical-align: top;
width: 250px;
margin-top: 50px;
margin-left: 50px;
background: lightblue;
}
input[type="range"].multirange.original {
position: absolute;
}
input[type="range"].multirange.original::-webkit-slider-thumb {
position: relative;
z-index: 2;
}
input[type="range"].multirange.original::-moz-range-thumb {
transform: scale(1);
/*FF doesn't apply position it seems*/
G z-index: 1;
}
input[type="range"].multirange::-moz-range-track {
border-color: transparent;
/* needed to switch FF to "styleable" control */
}
input[type="range"].multirange.ghost {
position: relative;
background: var(--track-background);
--track-background: linear-gradient(to right, transparent var(--low), var(--range-color) 0, var(--range-color) var(--high), transparent 0) no-repeat 0 45% / 100% 40%;
--range-color: hsl(190, 80%, 40%);
}
input[type="range"].multirange.ghost::-webkit-slider-runnable-track {
background: var(--track-background);
}
input[type="range"].multirange.ghost::-moz-range-track {
background: var(--track-background);
}
}
JavaScript
(function() {
"use strict";
var supportsMultiple = self.HTMLInputElement && "valueLow" in HTMLInputElement.prototype;
var descriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value");
self.multirange = function(input) {
if (supportsMultiple || input.classList.contains("multirange")) {
return;
}
var values = input.getAttribute("value").split(",");
var max = +input.max || 100;
var ghost = input.cloneNode();
input.classList.add("multirange", "original");
ghost.classList.add("multirange", "ghost");
input.value = values[0] || max / 2;
ghost.value = values[1] || max / 2;
input.parentNode.insertBefore(ghost, input.nextSibling);
Object.defineProperty(input, "originalValue", descriptor.get ? descriptor : {
// Dang you Safari >:(
get: function() {
return this.value;
},
set: function(v) {
this.value = v;
}
});
Object.defineProperties(input, {
valueLow: {
get: function() {
return Math.min(this.originalValue, ghost.value);
},
set: function(v) {
this.originalValue = v;
},
enumerable: true
},
valueHigh: {
get: function() {
return Math.max(this.originalValue, ghost.value);
},
set: function(v) {
ghost.value = v;
},
enumerable: true
}
});
if (descriptor.get) {
// Again, fuck you Safari
Object.defineProperty(input, "value", {
get: function() {
return this.valueLow + "," + this.valueHigh;
},
set: function(v) {
var values = v.split(",");
this.valueLow = values[0];
this.valueHigh = values[1];
},
enumerable: true
});
}
function update() {
ghost.style.setProperty("--low", input.valueLow * 100 / max + 1 + "%");
ghost.style.setProperty("--high", input.valueHigh * 100 / max - 1 +...