- let min = -50, max = 50;
- let thumbs = [
- { val: -15, lbl: 'Value A' },
- { val: 20, lbl: 'Value B' },
- { val: -35, lbl: 'Value C' },
- { val: 45, lbl: 'Value D' }
- ];
- let nv = thumbs.length;
- let tpos = thumbs.map((c, i) => `calc(var(--r) + (var(--v${i}) - var(--min))/var(--dif)*var(--uw))`);
- let fill = tpos.map(c => `linear-gradient(90deg, red ${c}, transparent 0)`);
- let hole = tpos.map(c => `radial-gradient(circle at ${c}, red var(--r), transparent 0)`)
.wrap(role='group' aria-labelledby='multi-lbl'
style=`${thumbs.map((c, i) => `--v${i}: ${c.val}`).join('; ')};
--min: ${min}; --max: ${max};
--fill: ${fill.join(', ')};
--hole: ${hole.join(', ')}`)
#multi-lbl Multi thumb slider:
- for(let i = 0; i < nv; i++)
label.sr-only(for=`v${i}`) #{thumbs[i].lbl}
input(type='range' id=`v${i}` min=min value=thumbs[i].val max=max)
output(for=`v${i}` style=`--c: var(--v${i})`)
View Compiled
$pad: 2em;
$hlc: #f90;
$t: .3s;
@mixin track() {
width: 100%; height: 100%;
background: none /* get rid of Firefox track background */
}
@mixin thumb() {
box-sizing: border-box; /* different between Chrome & Firefox */
/* box-sizing needed now that we have a non-zero border */
border: solid calc(.5*var(--r)) transparent;
width: var(--d); height: var(--d);
border-radius: 50%; /* make circular */
transform: scale(calc(1 - .5*var(--nothl)));
background: $hlc;
transition: transform $t ease-out;
pointer-events: auto
}
* {
--hl: 0;
--nothl: calc(1 - var(--hl));
margin: 0;
font: inherit
}
body {
display: grid;
place-content: center;
overflow-x: hidden;
min-height: 100vh;
background: url(https://images.unsplash.com/photo-1571388571275-971dc17e5ac8?ixlib=rb-1.2.1&q=85&fm=jpg&crop=entropy&cs=srgb&ixid=eyJhcHBfaWQiOjE0NTg5fQ) 50%/ cover #d7d7d7;
background-blend-mode: overlay;
}
.wrap {
--w: 20em;
--h: 1.75em;
--d: var(--h);
--r: calc(.5*var(--d));
--uw: calc(var(--w) - var(--d));
--dif: calc(var(--max) - var(--min));
display: grid;
grid-template-rows: max-content var(--h) max-content;
grid-gap: .625em;
overflow: hidden;
position: relative;
margin: 1em .5em - $pad;
padding: 0 $pad;
width: var(--w);
font: 700 1.125em ubuntu mono, consolas, monaco, monospace;
&::before, &::after {
grid-column: 1;
grid-row: 2;
align-self: center;
height: 6px;
border-radius: var(--r);
background:
repeating-linear-gradient(-45deg,
grey, grey 3px, transparent 0, transparent 7px) #fff;
color: #eee;
--mask: linear-gradient(red, red), var(--hole);
/* non-standard WebKit version */
mask: var(--mask);
mask-composite: xor;
/* standard version, supported in Firefox */
mask: var(--mask);
mask-composite: exclude;
content: ''
}
&::after {
background: #95a;
filter: Grayscale(var(--nothl));
--mask: var(--fill);
transition: filter $t ease-out
}
&:focus-within { --hl: 1 }
}
.sr-only {
position: absolute;
clip-path: inset(50%)
}
input[type='range'] {
&::slider-runnable-track,
&::slider-thumb, & {
appearance: none
}
grid-column: 1;
grid-row: 2;
z-index: calc(1 + var(--hl));
top: 0; left: 0;
background: none; /* get rid of white Chrome background */
filter: grayScale(var(--nothl));
transition: filter $t ease-out;
cursor: grab;
pointer-events: none;
&::slider-runnable-track { @include track }
&::range-track { @include track }
&::slider-thumb { @include thumb }
&::range-thumb { @include thumb }
&:focus {
outline: solid 0 transparent;
&, & + output { --hl: 1 }
}
&:active { cursor: grabbing }
}
output {
grid-column: 1;
grid-row: 3;
margin-left: var(--r);
max-width: max-content;
transform: translate(calc((var(--c) - var(--min))/var(--dif)*var(--uw)));
&::after {
display: block;
border-radius: 5px;
padding: 0 .375em;
transform: translate(-50%) scale(var(--hl));
background: $hlc;
color: #fff;
transition: transform $t ease-out;
counter-reset: c var(--c);
content: counter(c)
}
}
View Compiled
addEventListener('input', e => {
let _t = e.target;
_t.parentNode.style.setProperty(`--${_t.id}`, +_t.value)
}, false);
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.