<body>
<main>
<div class="field">
<label class="text-label">Text label</label>
<div class="inputslider" data-value="40" data-unit="%" data-values="20,25,30,35,40,45,50">
<input type="text" name="input" autocomplete="off" readonly>
<div class="values"></div>
<div class="area">
<div class="track"></div>
<div class="fill"></div>
<div class="knob"></div>
</div>
</div>
</div>
</main>
</body>
html {
width: 100%;
height: 100%;
}
body {
background-color: #E6E9ED;
width: 100%;
height: 100%;
}
main {
width: 100%;
height: 100%;
display: grid;
align-items: center;
}
.field {
background-color: #fff;
width: 100%;
max-width: 340px;
padding: 20px;
margin-left: auto;
margin-right: auto;
box-shadow: 0px 10px 20px 0px rgba(0,0,0,0.19), 0px 6px 6px 0px rgba(0,0,0,0.23);
label {
margin-bottom: 16px;
display: block;
font-weight: bold;
font-size: 16px;
}
}
.inputslider {
position: relative;
input {
display: none;
}
.values {
position: relative;
margin-left: 14px;
margin-right: 14px;
height: 30px;
margin-bottom: 8px;
z-index: 1;
span {
position: absolute;
top: 0;
background-color: #E6E9ED;
color: #434A54;
line-height: 20px;
padding: 0 10px;
border-radius: 10px;
text-align: center;
white-space: nowrap;
display: block;
font-size: 12px;
transform: translateX(-50%);
z-index: 1;
transition: all .2s ease;
&.selected {
background-color: #434A54;
color: #fff;
z-index: 2;
}
}
}
.area {
position: relative;
height: 28px;
.track {
position: absolute;
top: 50%;
left: 0;
background-color: #E6E9ED;
width: 100%;
height: 6px;
border-radius: 3px;
z-index: 1;
transform: translateY(-50%);
}
.fill {
position: absolute;
top: 50%;
left: 0;
background: #AAB2BD;
width: 0;
height: 6px;
border-radius: 3px;
z-index: 2;
transform: translateY(-50%);
}
.knob {
position: absolute;
top: 0;
left: 0;
background-color: #434A54;
width: 28px;
height: 28px;
border-radius: 50%;
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.1), 0px 7px 12px rgba(0, 0, 0, 0.12);
z-index: 3;
}
}
}
View Compiled
Element.prototype.addClass = function(className)
{
if(!this.classList.contains(className)){
this.classList.add(className);
}
};
Element.prototype.removeClass = function(className)
{
if(this.classList.contains(className)){
this.classList.remove(className);
}
};
Array.prototype.first = function()
{
return this[0];
}
Array.prototype.last = function()
{
return this[this.length - 1];
}
document.querySelectorAll('.inputslider').forEach(
(inputslider) => {
let values = inputslider.dataset.values.split(','),
value = parseFloat(inputslider.dataset.value),
unit = '',
min = parseFloat(values.first()),
max = parseFloat(values.last()),
input = inputslider.querySelector('input'),
area = inputslider.querySelector('.area'),
knob = inputslider.querySelector('.knob'),
fill = inputslider.querySelector('.fill');
if(inputslider.dataset.unit){
unit = inputslider.dataset.unit;
}
values.forEach(
(value, i) => {
values[i] = value = parseFloat(value);
let span = document.createElement('span');
span.innerText = value + unit;
span.setAttribute('data-value', value);
if(i == 0){
span.addClass('selected');
input.value = value;
}
span.style.left = gsap.utils.mapRange(min, max, 0, 100, value) + '%';
inputslider.querySelector('.values').appendChild(span);
}
);
Draggable.create(knob, {
type: 'x',
edgeResistance: 1,
bounds: area,
throwProps: false,
onDrag: function()
{
handleInputslider(this, false);
},
onDragEnd: function()
{
handleInputslider(this, true);
}
}
);
}
);
function handleInputslider(instance, snap)
{
let inputslider = instance.target.closest('.inputslider'),
fill = inputslider.querySelector('.fill'),
values = inputslider.dataset.values.split(','),
min = parseFloat(values.first()),
max = parseFloat(values.last()),
xPercent = gsap.utils.mapRange(0, instance.maxX, 0, 100, instance.x),
relativeValue = gsap.utils.mapRange(0, instance.maxX, min, max, instance.x),
finalValue = gsap.utils.snap(values, relativeValue),
snapX = gsap.utils.mapRange(min, max, 0, instance.maxX, finalValue),
fillWidth = gsap.utils.mapRange(0, instance.maxX, 0, 100, snapX);
if(snap){
gsap.to(instance.target, {duration: .2, x: snapX});
gsap.to(fill, {duration: .2, width: fillWidth + '%'});
}else{
values.forEach(
(value, i) => {
values[i] = parseFloat(value);
}
);
fill.style.width = xPercent + '%';
inputslider.querySelectorAll('.values span').forEach(
(span) => {
if(parseFloat(span.dataset.value) == finalValue){
span.addClass('selected');
}else{
span.removeClass('selected');
}
}
);
inputslider.querySelector('input').value = finalValue;
}
}
This Pen doesn't use any external CSS resources.