<form>
<div class="form__block">
<label for="range1">A</label>
<input id="range1" name="range1" type="range" min="0" max="5" value="3">
</div>
<div class="form__block">
<label for="range2">B</label>
<input id="range2" name="range2" type="range" min="0" max="10" value="5">
</div>
<div class="form__block">
<label for="range3">C</label>
<input id="range3" name="range3" type="range" min="0" max="20" value="10">
</div>
<div class="form__block">
<label for="range4">D</label>
<input id="range4" name="range4" type="range" min="0" max="25" value="13">
</div>
<div class="form__block">
<label for="range5">E</label>
<input id="range5" name="range5" type="range" min="0" max="30" value="15">
</div>
<div class="form__block">
<label for="range6">F</label>
<input id="range6" name="range6" type="range" min="0" max="40" value="20">
</div>
<div class="form__block">
<label for="range7">G</label>
<input id="range7" name="range7" type="range" min="0" max="50" value="25">
</div>
<div class="form__block">
<label for="range8">H</label>
<input id="range8" name="range8" type="range" min="0" max="60" value="30">
</div>
<div class="form__block">
<label for="range9">I</label>
<input id="range9" name="range9" type="range" min="0" max="70" value="35">
</div>
<div class="form__block">
<label for="range10">J</label>
<input id="range10" name="range10" type="range" min="0" max="80" value="40">
</div>
<div class="form__block">
<label for="range11">K</label>
<input id="range11" name="range11" type="range" min="0" max="90" value="45">
</div>
<div class="form__block">
<label for="range12">L</label>
<input id="range12" name="range12" type="range" min="0" max="100" value="50">
</div>
</form>
// mixins
@mixin thumbBaseProps()
background: transparent
border: 0
width: 1px
height: 1.5em
appearance: none
appearance: none
appearance: none
// normal styles
*
border: 0
box-sizing: border-box
margin: 0
padding: 0
\:root
--bg: hsl(223,10%,90%)
--fg: hsl(223,10%,10%)
--orange: hsl(29,90%,55%)
--yellow: hsl(43,90%,55%)
--blue: hsl(198,90%,55%)
--white: hsl(223,10%,100%)
font-size: calc(20px + (30 - 20) * (100vw - 320px) / (1280 - 320))
body, input
font: 1em/1.5 "Jost", system-ui, -apple-system, sans-serif
body
background: var(--bg)
color: var(--fg)
display: flex
height: 100vh
form
display: grid
grid:
gap: 0 1.5em
template-columns: repeat(2,1fr)
margin: auto
label
display: block
.range-pill
--pillWidth: 4.5em
box-shadow: 0 0.375em 0.375em 0 hsla(0,0%,0%,0.3)
display: inline-block
overflow: hidden
position: relative
width: var(--pillWidth)
height: 1.5em
&, &:before, &__input
border-radius: 0.75em
&:before, &:after, &__fill, &__input, &__value
display: block
position: absolute
&:before, &__fill, &__input, &__value
top: 0
left: 0
height: 100%
&:before, &__input, &__value
width: 100%
&:before, &:after
content: ""
z-index: 3
&:before
background: radial-gradient(0.5em 0.4em at 0.75em 0.5em,hsla(0,0%,100%,0.25) 30%,hsla(0,0%,100%,0) 50%)
box-shadow: 0.05em -0.025em 0.25em 0.05em hsla(0,0%,100%,0.4) inset, 0.125em -0.125em 0.15em 0.25em hsla(0,0%,100%,0.07) inset, 0 -0.75em 0.175em 0 hsla(0,0%,0%,0.07) inset, 0 -0.4em 0.05em 0.2em hsla(0,0%,100%,0.07) inset, 0 -0.125em 0.05em 0.2em hsla(0,0%,100%,0.1) inset
&:after
background: hsla(0,0%,100%,0.25)
border-radius: 0.125em
box-shadow: 0 0 0.1em 0.1em hsla(0,0%,100%,0.25)
top: 0.6em
left: 1.25em
width: calc(var(--pillWidth) - 1.75em)
height: 0.1em
&--orange-track, &--orange-thumb &__fill
background: var(--orange)
&--yellow-track, &--yellow-thumb &__fill
background: var(--yellow)
&--blue-track, &--blue-thumb &__fill
background: var(--blue)
&--white-track, &--white-thumb &__fill
background: var(--white)
&__fill
box-shadow: 0 0 0.1em hsl(223,10%,10%), -0.05em 0 0 hsla(0,0%,100%,0.3) inset
z-index: 1
&__input
background: transparent
cursor: pointer
z-index: 4
appearance: none
appearance: none
appearance: none
tap-highlight-color: transparent
&:focus
outline: transparent
&-visible
box-shadow: 0 0 0.125em 0.125em hsl(223,90%,45%) inset
&::-moz-focus-outer
border: 0
&::-webkit-slider-thumb
@include thumbBaseProps()
&::-moz-range-thumb
@include thumbBaseProps()
&__value
color: hsl(223,10%,10%)
font-size: 0.75em
line-height: 2
text:
align: center
shadow: 0 0 0.2em hsla(223,10%,10%,0.3), 0.1em 0.1em 0.1em hsla(223,10%,10%,0.3)
z-index: 2
// dark mode
@media (prefers-color-scheme: dark)
\:root
--bg: hsl(223,10%,20%)
--fg: hsl(223,10%,90%)
.range-pill
box-shadow: 0 0.375em 0.375em 0 hsla(0,0%,0%,0.3)
&:before
background: radial-gradient(0.5em 0.4em at 0.75em 0.5em,hsla(0,0%,100%,0.2) 30%,hsla(0,0%,100%,0) 50%)
box-shadow: 0.05em -0.025em 0.25em 0.05em hsla(223,10%,20%,0.4) inset, 0.125em -0.125em 0.15em 0.25em hsla(223,10%,20%,0.07) inset, 0 -0.75em 0.175em 0 hsla(0,0%,0%,0.07) inset, 0 -0.4em 0.05em 0.2em hsla(223,10%,20%,0.07) inset, 0 -0.125em 0.05em 0.2em hsla(223,10%,20%,0.1) inset
// larger viewports
@media (min-width: 480px)
form
grid:
template-columns: repeat(3,1fr)
@media (min-width: 768px)
form
grid:
template-columns: repeat(4,1fr)
View Compiled
document.addEventListener("DOMContentLoaded",function(){
let ranges = [
new RangePill("#range1","orange"),
new RangePill("#range2","yellow"),
new RangePill("#range3","blue"),
new RangePill("#range4","white","orange"),
new RangePill("#range5","white","yellow"),
new RangePill("#range6","white","blue"),
new RangePill("#range7","orange","yellow"),
new RangePill("#range8","blue","orange"),
new RangePill("#range9","yellow","blue"),
new RangePill("#range10","yellow","orange"),
new RangePill("#range11","orange","blue"),
new RangePill("#range12","blue","yellow")
];
});
class RangePill {
constructor(qs,thumbColor = "orange",trackColor = "white") {
this.el = document.querySelector(qs);
this.fill = null;
this.value = null;
if (this.el) {
this.buildSlider(thumbColor,trackColor);
this.el.addEventListener("input",this.changeValue.bind(this));
}
}
buildSlider(thumbColor,trackColor) {
this.el.className = "range-pill__input";
// create a div to contain the <input>
let rangeWrap = document.createElement("span");
rangeWrap.className = "range-pill";
// thumb and track colors
if (thumbColor)
rangeWrap.classList.add(`range-pill--${thumbColor}-thumb`);
if (trackColor)
rangeWrap.classList.add(`range-pill--${trackColor}-track`);
this.el.parentElement.insertBefore(rangeWrap,this.el);
// input
rangeWrap.appendChild(this.el);
// range fill
let rangeFill = document.createElement("span");
rangeFill.className = "range-pill__fill";
rangeWrap.appendChild(rangeFill);
// range value
let rangeValue = document.createElement("span");
rangeValue.className = "range-pill__value";
rangeValue.textContent = this.el.value;
rangeWrap.appendChild(rangeValue);
// initial value
this.fill = rangeFill;
this.value = rangeValue;
this.changeValue();
}
changeValue() {
// keep the value within range
if (+this.el.value > this.el.max)
this.el.value = this.el.max;
else if (+this.el.value < this.el.min)
this.el.value = this.el.min;
// width of fill
if (this.fill) {
let pct = (this.el.value - this.el.min) / (this.el.max - this.el.min),
fillWidth = pct * 100;
this.fill.style.width = `${fillWidth}%`;
}
// value
if (this.value)
this.value.textContent = this.el.value;
}
}
This Pen doesn't use any external JavaScript resources.