Open demo

CSS code

HTML
<div><span class="lbl">Neon glow</span><div class="card">
<div class="dk neon">
  <div class="dk-head"><label for="dk-bass">Bass boost</label><output for="dk-bass">72%</output></div>
  <input type="range" id="dk-bass" min="0" max="100" value="72" data-suffix="%">
  <div class="dk-scale" aria-hidden="true"><span>Off</span><span>Max</span></div>
</div></div></div>

<div><span class="lbl">Centre zero</span><div class="card">
<div class="dk zero">
  <div class="dk-head"><label for="dk-ev">Exposure</label><output for="dk-ev">+0.7 EV</output></div>
  <input type="range" id="dk-ev" min="-2" max="2" step="0.1" value="0.7" data-signed data-decimals="1" data-suffix=" EV">
  <div class="dk-scale" aria-hidden="true"><span>−2</span><span>0</span><span>+2</span></div>
</div></div></div>

<div><span class="lbl">LED level</span><div class="card">
<div class="dk led">
  <div class="dk-head"><label for="dk-fan">Fan speed</label><output for="dk-fan">6 of 10</output></div>
  <input type="range" id="dk-fan" min="1" max="10" value="6" data-suffix=" of 10">
</div></div></div>

<div><span class="lbl">Hue picker</span><div class="card">
<div class="dk hue">
  <div class="dk-head"><label for="dk-hue">Accent hue</label><output for="dk-hue"><span class="dk-swatch" aria-hidden="true"></span><span class="dk-text">262°</span></output></div>
  <input type="range" id="dk-hue" min="0" max="360" value="262" data-suffix="°">
</div></div></div>
CSS
/* Dark range sliders for dark interfaces. A real <input type="range"> styled through the WebKit and Firefox
   pseudo-elements; --p (0 to 1) is set by the script below. Every track is at least 3:1 against #121a2e. */
.dk{--dk-accent:#22d3ee;--dk-track:#5f6f8a;--dk-bg:#121a2e;--dk-thumb:20px;--dk-h:6px;--p:0;display:grid;gap:14px}
.dk-head{display:flex;justify-content:space-between;align-items:baseline;gap:12px}
.dk-head label{font-size:.95rem;font-weight:600;color:#e2e8f0}
.dk-head output{font-size:.95rem;font-weight:700;color:var(--dk-accent);font-variant-numeric:tabular-nums}
.dk input[type="range"]{-webkit-appearance:none;appearance:none;display:block;width:100%;height:var(--dk-thumb);margin:0;background:none;cursor:pointer}
.dk input[type="range"]:focus-visible{outline:none}
.dk input[type="range"]::-webkit-slider-runnable-track{height:var(--dk-h);border-radius:999px;
  background:linear-gradient(to right,var(--dk-accent) 0 calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p)),var(--dk-track) 0)}
.dk input[type="range"]::-moz-range-track{height:var(--dk-h);border-radius:999px;
  background:linear-gradient(to right,var(--dk-accent) 0 calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p)),var(--dk-track) 0)}
.dk input[type="range"]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;box-sizing:border-box;
  width:var(--dk-thumb);height:var(--dk-thumb);margin-top:calc((var(--dk-h) - var(--dk-thumb)) / 2);
  border:0;border-radius:50%;background:#fff;box-shadow:0 0 0 4px rgba(34,211,238,.25),0 0 14px rgba(34,211,238,.7)}
.dk input[type="range"]::-moz-range-thumb{box-sizing:border-box;width:var(--dk-thumb);height:var(--dk-thumb);
  border:0;border-radius:50%;background:#fff;box-shadow:0 0 0 4px rgba(34,211,238,.25),0 0 14px rgba(34,211,238,.7)}
.dk input[type="range"]:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 3px var(--dk-bg),0 0 0 5px #fff}
.dk input[type="range"]:focus-visible::-moz-range-thumb{box-shadow:0 0 0 3px var(--dk-bg),0 0 0 5px #fff}
/* neon: the filled part glows */
.dk.neon input[type="range"]::-webkit-slider-runnable-track{box-shadow:0 0 12px rgba(34,211,238,.35)}
.dk.neon input[type="range"]::-moz-range-track{box-shadow:0 0 12px rgba(34,211,238,.35)}
/* centre zero: fill runs from the middle to the thumb, a tick marks 0 */
.dk.zero{--dk-accent:#fbbf24}
.dk.zero input[type="range"]::-webkit-slider-runnable-track{background:
  linear-gradient(#e2e8f0,#e2e8f0) center / 2px 100% no-repeat,
  linear-gradient(to right,var(--dk-track) 0 min(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),
    var(--dk-accent) 0 max(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),var(--dk-track) 0)}
.dk.zero input[type="range"]::-moz-range-track{background:
  linear-gradient(#e2e8f0,#e2e8f0) center / 2px 100% no-repeat,
  linear-gradient(to right,var(--dk-track) 0 min(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),
    var(--dk-accent) 0 max(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),var(--dk-track) 0)}
.dk.zero input[type="range"]::-webkit-slider-thumb{background:var(--dk-accent);box-shadow:0 0 0 4px rgba(251,191,36,.2)}
.dk.zero input[type="range"]::-moz-range-thumb{background:var(--dk-accent);box-shadow:0 0 0 4px rgba(251,191,36,.2)}
.dk-scale{display:flex;justify-content:space-between;font-size:.78rem;color:#94a3b8;font-variant-numeric:tabular-nums}
/* LED level: ten blocks light up to the thumb; the gaps are painted in the card colour */
.dk.led{--dk-accent:#a3e635;--dk-thumb:6px;--dk-h:14px}
.dk.led input[type="range"]{height:28px}
.dk.led input[type="range"]::-webkit-slider-runnable-track{border-radius:3px;background:
  repeating-linear-gradient(to right,transparent 0 calc(10% - 4px),var(--dk-bg) 0 10%),
  linear-gradient(to right,var(--dk-accent) 0 calc((var(--p) * 9 + 1) * 10%),var(--dk-track) 0)}
.dk.led input[type="range"]::-moz-range-track{border-radius:3px;background:
  repeating-linear-gradient(to right,transparent 0 calc(10% - 4px),var(--dk-bg) 0 10%),
  linear-gradient(to right,var(--dk-accent) 0 calc((var(--p) * 9 + 1) * 10%),var(--dk-track) 0)}
.dk.led input[type="range"]::-webkit-slider-thumb{width:6px;height:28px;margin-top:-7px;border-radius:3px;box-shadow:0 0 0 2px var(--dk-bg)}
.dk.led input[type="range"]::-moz-range-thumb{width:6px;height:28px;border-radius:3px;box-shadow:0 0 0 2px var(--dk-bg)}
.dk.led input[type="range"]:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--dk-bg),0 0 0 4px #fff}
.dk.led input[type="range"]:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px var(--dk-bg),0 0 0 4px #fff}
/* hue: the track is the colour wheel unrolled and the thumb takes the chosen hue */
.dk.hue{--dk-thumb:26px;--dk-h:12px}
.dk.hue .dk-head output{color:#e2e8f0;display:inline-flex;align-items:center;gap:8px}
.dk-swatch{width:14px;height:14px;border-radius:4px;background:hsl(calc(var(--p) * 360) 85% 60%);box-shadow:0 0 0 1px rgba(255,255,255,.4)}
.dk.hue input[type="range"]::-webkit-slider-runnable-track{background:linear-gradient(to right,
  hsl(0 85% 60%),hsl(60 85% 60%),hsl(120 85% 60%),hsl(180 85% 60%),hsl(240 85% 60%),hsl(300 85% 60%),hsl(360 85% 60%))}
.dk.hue input[type="range"]::-moz-range-track{background:linear-gradient(to right,
  hsl(0 85% 60%),hsl(60 85% 60%),hsl(120 85% 60%),hsl(180 85% 60%),hsl(240 85% 60%),hsl(300 85% 60%),hsl(360 85% 60%))}
.dk.hue input[type="range"]::-webkit-slider-thumb{border:4px solid #fff;background:hsl(calc(var(--p) * 360) 85% 60%);box-shadow:0 2px 8px rgba(0,0,0,.5)}
.dk.hue input[type="range"]::-moz-range-thumb{border:4px solid #fff;background:hsl(calc(var(--p) * 360) 85% 60%);box-shadow:0 2px 8px rgba(0,0,0,.5)}
JavaScript
// Keeps each slider's fill (--p) and its readout in step with the value.
document.querySelectorAll('.dk input[type="range"]').forEach(function (range) {
  var field = range.closest('.dk');
  var out = field.querySelector('.dk-text') || field.querySelector('output');
  function sync() {
    var v = Number(range.value), d = Number(range.dataset.decimals || 0);
    var sign = v < 0 ? '−' : (v > 0 && range.hasAttribute('data-signed') ? '+' : '');
    var text = sign + Math.abs(v).toFixed(d) + (range.dataset.suffix || '');
    field.style.setProperty('--p', (v - range.min) / (range.max - range.min));
    out.textContent = text;
    range.setAttribute('aria-valuetext', text);
  }
  range.addEventListener('input', sync);
  sync();
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Neon glow</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk neon">
  <div class="d-flex justify-content-between align-items-baseline gap-3"><label class="form-label fw-semibold mb-0" for="dk-bass">Bass boost</label><output class="dk-value fw-bold" for="dk-bass">72%</output></div>
  <input type="range" class="form-range" id="dk-bass" min="0" max="100" value="72" data-suffix="%">
  <div class="dk-scale d-flex justify-content-between" aria-hidden="true"><span>Off</span><span>Max</span></div>
</div></div></div></div>

<div><span class="lbl">Centre zero</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk zero">
  <div class="d-flex justify-content-between align-items-baseline gap-3"><label class="form-label fw-semibold mb-0" for="dk-ev">Exposure</label><output class="dk-value fw-bold" for="dk-ev">+0.7 EV</output></div>
  <input type="range" class="form-range" id="dk-ev" min="-2" max="2" step="0.1" value="0.7" data-signed data-decimals="1" data-suffix=" EV">
  <div class="dk-scale d-flex justify-content-between" aria-hidden="true"><span>−2</span><span>0</span><span>+2</span></div>
</div></div></div></div>

<div><span class="lbl">LED level</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk led">
  <div class="d-flex justify-content-between align-items-baseline gap-3"><label class="form-label fw-semibold mb-0" for="dk-fan">Fan speed</label><output class="dk-value fw-bold" for="dk-fan">6 of 10</output></div>
  <input type="range" class="form-range" id="dk-fan" min="1" max="10" value="6" data-suffix=" of 10">
</div></div></div></div>

<div><span class="lbl">Hue picker</span><div class="card demo-card"><div class="card-body p-4">
<div class="dk hue">
  <div class="d-flex justify-content-between align-items-baseline gap-3"><label class="form-label fw-semibold mb-0" for="dk-hue">Accent hue</label><output class="dk-value fw-bold d-inline-flex align-items-center gap-2" for="dk-hue"><span class="dk-swatch" aria-hidden="true"></span><span class="dk-text">262°</span></output></div>
  <input type="range" class="form-range" id="dk-hue" min="0" max="360" value="262" data-suffix="°">
</div></div></div></div>
CSS
/* Dark range sliders: Bootstrap .form-range under data-bs-theme="dark", restyled through the WebKit and Firefox
   pseudo-elements; --p (0 to 1) is set by the script below. Every track is at least 3:1 against #121a2e. */
.dk{--dk-accent:#22d3ee;--dk-track:#5f6f8a;--dk-bg:#121a2e;--dk-thumb:20px;--dk-h:6px;--p:0;display:grid;gap:14px}
.dk .form-label{font-size:.95rem;color:#e2e8f0}
.dk .dk-value{font-size:.95rem;color:var(--dk-accent);font-variant-numeric:tabular-nums}
.dk .form-range{height:var(--dk-thumb)}
.dk .form-range::-webkit-slider-runnable-track{height:var(--dk-h);border-radius:999px;
  background:linear-gradient(to right,var(--dk-accent) 0 calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p)),var(--dk-track) 0)}
.dk .form-range::-moz-range-track{height:var(--dk-h);border-radius:999px;
  background:linear-gradient(to right,var(--dk-accent) 0 calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p)),var(--dk-track) 0)}
.dk .form-range::-webkit-slider-thumb{box-sizing:border-box;
  width:var(--dk-thumb);height:var(--dk-thumb);margin-top:calc((var(--dk-h) - var(--dk-thumb)) / 2);
  border:0;border-radius:50%;background:#fff;box-shadow:0 0 0 4px rgba(34,211,238,.25),0 0 14px rgba(34,211,238,.7)}
.dk .form-range::-moz-range-thumb{box-sizing:border-box;width:var(--dk-thumb);height:var(--dk-thumb);
  border:0;border-radius:50%;background:#fff;box-shadow:0 0 0 4px rgba(34,211,238,.25),0 0 14px rgba(34,211,238,.7)}
.dk .form-range:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 3px var(--dk-bg),0 0 0 5px #fff}
.dk .form-range:focus-visible::-moz-range-thumb{box-shadow:0 0 0 3px var(--dk-bg),0 0 0 5px #fff}
/* neon: the filled part glows */
.dk.neon .form-range::-webkit-slider-runnable-track{box-shadow:0 0 12px rgba(34,211,238,.35)}
.dk.neon .form-range::-moz-range-track{box-shadow:0 0 12px rgba(34,211,238,.35)}
/* centre zero: fill runs from the middle to the thumb, a tick marks 0 */
.dk.zero{--dk-accent:#fbbf24}
.dk.zero .form-range::-webkit-slider-runnable-track{background:
  linear-gradient(#e2e8f0,#e2e8f0) center / 2px 100% no-repeat,
  linear-gradient(to right,var(--dk-track) 0 min(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),
    var(--dk-accent) 0 max(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),var(--dk-track) 0)}
.dk.zero .form-range::-moz-range-track{background:
  linear-gradient(#e2e8f0,#e2e8f0) center / 2px 100% no-repeat,
  linear-gradient(to right,var(--dk-track) 0 min(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),
    var(--dk-accent) 0 max(50%,calc(var(--dk-thumb) / 2 + (100% - var(--dk-thumb)) * var(--p))),var(--dk-track) 0)}
.dk.zero .form-range::-webkit-slider-thumb{background:var(--dk-accent);box-shadow:0 0 0 4px rgba(251,191,36,.2)}
.dk.zero .form-range::-moz-range-thumb{background:var(--dk-accent);box-shadow:0 0 0 4px rgba(251,191,36,.2)}
.dk-scale{font-size:.78rem;color:#94a3b8;font-variant-numeric:tabular-nums}
/* LED level: ten blocks light up to the thumb; the gaps are painted in the card colour */
.dk.led{--dk-accent:#a3e635;--dk-thumb:6px;--dk-h:14px}
.dk.led .form-range{height:28px}
.dk.led .form-range::-webkit-slider-runnable-track{border-radius:3px;background:
  repeating-linear-gradient(to right,transparent 0 calc(10% - 4px),var(--dk-bg) 0 10%),
  linear-gradient(to right,var(--dk-accent) 0 calc((var(--p) * 9 + 1) * 10%),var(--dk-track) 0)}
.dk.led .form-range::-moz-range-track{border-radius:3px;background:
  repeating-linear-gradient(to right,transparent 0 calc(10% - 4px),var(--dk-bg) 0 10%),
  linear-gradient(to right,var(--dk-accent) 0 calc((var(--p) * 9 + 1) * 10%),var(--dk-track) 0)}
.dk.led .form-range::-webkit-slider-thumb{width:6px;height:28px;margin-top:-7px;border-radius:3px;box-shadow:0 0 0 2px var(--dk-bg)}
.dk.led .form-range::-moz-range-thumb{width:6px;height:28px;border-radius:3px;box-shadow:0 0 0 2px var(--dk-bg)}
.dk.led .form-range:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 2px var(--dk-bg),0 0 0 4px #fff}
.dk.led .form-range:focus-visible::-moz-range-thumb{box-shadow:0 0 0 2px var(--dk-bg),0 0 0 4px #fff}
/* hue: the track is the colour wheel unrolled and the thumb takes the chosen hue */
.dk.hue{--dk-thumb:26px;--dk-h:12px}
.dk.hue .dk-value{color:#e2e8f0}
.dk-swatch{width:14px;height:14px;border-radius:4px;background:hsl(calc(var(--p) * 360) 85% 60%);box-shadow:0 0 0 1px rgba(255,255,255,.4)}
.dk.hue .form-range::-webkit-slider-runnable-track{background:linear-gradient(to right,
  hsl(0 85% 60%),hsl(60 85% 60%),hsl(120 85% 60%),hsl(180 85% 60%),hsl(240 85% 60%),hsl(300 85% 60%),hsl(360 85% 60%))}
.dk.hue .form-range::-moz-range-track{background:linear-gradient(to right,
  hsl(0 85% 60%),hsl(60 85% 60%),hsl(120 85% 60%),hsl(180 85% 60%),hsl(240 85% 60%),hsl(300 85% 60%),hsl(360 85% 60%))}
.dk.hue .form-range::-webkit-slider-thumb{border:4px solid #fff;background:hsl(calc(var(--p) * 360) 85% 60%);box-shadow:0 2px 8px rgba(0,0,0,.5)}
.dk.hue .form-range::-moz-range-thumb{border:4px solid #fff;background:hsl(calc(var(--p) * 360) 85% 60%);box-shadow:0 2px 8px rgba(0,0,0,.5)}
JavaScript
// Keeps each slider's fill (--p) and its readout in step with the value.
document.querySelectorAll('.dk .form-range').forEach(function (range) {
  var field = range.closest('.dk');
  var out = field.querySelector('.dk-text') || field.querySelector('output');
  function sync() {
    var v = Number(range.value), d = Number(range.dataset.decimals || 0);
    var sign = v < 0 ? '−' : (v > 0 && range.hasAttribute('data-signed') ? '+' : '');
    var text = sign + Math.abs(v).toFixed(d) + (range.dataset.suffix || '');
    field.style.setProperty('--p', (v - range.min) / (range.max - range.min));
    out.textContent = text;
    range.setAttribute('aria-valuetext', text);
  }
  range.addEventListener('input', sync);
  sync();
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#94a3b8] uppercase">Neon glow</span><div class="rounded-2xl border border-[#1f2a44] bg-dk-bg px-6 pt-[22px] pb-6">
<div class="dk grid gap-3.5 [--p:0]">
  <div class="flex items-baseline justify-between gap-3"><label for="dk-bass" class="text-[.95rem] font-semibold">Bass boost</label><output for="dk-bass" class="text-[.95rem] font-bold text-dk-cyan tabular-nums">72%</output></div>
  <input type="range" id="dk-bass" min="0" max="100" value="72" data-suffix="%" class="block h-[20px] w-full cursor-pointer appearance-none bg-transparent focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-[6px] [&::-webkit-slider-runnable-track]:rounded-full [&::-moz-range-track]:h-[6px] [&::-moz-range-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,var(--color-dk-cyan)_0_calc(10px_+_(100%_-_20px)_*_var(--p)),var(--color-dk-track)_0)] [&::-moz-range-track]:bg-[linear-gradient(to_right,var(--color-dk-cyan)_0_calc(10px_+_(100%_-_20px)_*_var(--p)),var(--color-dk-track)_0)] [&::-webkit-slider-thumb]:-mt-[7px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-[20px] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-0 [&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:shadow-[0_0_0_4px_rgba(34,211,238,.25),0_0_14px_rgba(34,211,238,.7)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-[20px] [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 [&::-moz-range-thumb]:bg-white [&::-moz-range-thumb]:shadow-[0_0_0_4px_rgba(34,211,238,.25),0_0_14px_rgba(34,211,238,.7)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_3px_var(--color-dk-bg),0_0_0_5px_#fff] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_3px_var(--color-dk-bg),0_0_0_5px_#fff] [&::-webkit-slider-runnable-track]:shadow-[0_0_12px_rgba(34,211,238,.35)] [&::-moz-range-track]:shadow-[0_0_12px_rgba(34,211,238,.35)]">
  <div class="flex justify-between text-[.78rem] text-[#94a3b8] tabular-nums" aria-hidden="true"><span>Off</span><span>Max</span></div>
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#94a3b8] uppercase">Centre zero</span><div class="rounded-2xl border border-[#1f2a44] bg-dk-bg px-6 pt-[22px] pb-6">
<div class="dk grid gap-3.5 [--p:0]">
  <div class="flex items-baseline justify-between gap-3"><label for="dk-ev" class="text-[.95rem] font-semibold">Exposure</label><output for="dk-ev" class="text-[.95rem] font-bold text-dk-amber tabular-nums">+0.7 EV</output></div>
  <input type="range" id="dk-ev" min="-2" max="2" step="0.1" value="0.7" data-signed data-decimals="1" data-suffix=" EV" class="block h-[20px] w-full cursor-pointer appearance-none bg-transparent focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-[6px] [&::-webkit-slider-runnable-track]:rounded-full [&::-moz-range-track]:h-[6px] [&::-moz-range-track]:rounded-full [&::-webkit-slider-runnable-track]:[background:linear-gradient(#e2e8f0,#e2e8f0)_center/2px_100%_no-repeat,linear-gradient(to_right,var(--color-dk-track)_0_min(50%,calc(10px_+_(100%_-_20px)_*_var(--p))),var(--color-dk-amber)_0_max(50%,calc(10px_+_(100%_-_20px)_*_var(--p))),var(--color-dk-track)_0)] [&::-moz-range-track]:[background:linear-gradient(#e2e8f0,#e2e8f0)_center/2px_100%_no-repeat,linear-gradient(to_right,var(--color-dk-track)_0_min(50%,calc(10px_+_(100%_-_20px)_*_var(--p))),var(--color-dk-amber)_0_max(50%,calc(10px_+_(100%_-_20px)_*_var(--p))),var(--color-dk-track)_0)] [&::-webkit-slider-thumb]:-mt-[7px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-[20px] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-0 [&::-webkit-slider-thumb]:bg-dk-amber [&::-webkit-slider-thumb]:shadow-[0_0_0_4px_rgba(251,191,36,.2)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-[20px] [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-0 [&::-moz-range-thumb]:bg-dk-amber [&::-moz-range-thumb]:shadow-[0_0_0_4px_rgba(251,191,36,.2)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_3px_var(--color-dk-bg),0_0_0_5px_#fff] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_3px_var(--color-dk-bg),0_0_0_5px_#fff]">
  <div class="flex justify-between text-[.78rem] text-[#94a3b8] tabular-nums" aria-hidden="true"><span>−2</span><span>0</span><span>+2</span></div>
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#94a3b8] uppercase">LED level</span><div class="rounded-2xl border border-[#1f2a44] bg-dk-bg px-6 pt-[22px] pb-6">
<div class="dk grid gap-3.5 [--p:0]">
  <div class="flex items-baseline justify-between gap-3"><label for="dk-fan" class="text-[.95rem] font-semibold">Fan speed</label><output for="dk-fan" class="text-[.95rem] font-bold text-dk-lime tabular-nums">6 of 10</output></div>
  <input type="range" id="dk-fan" min="1" max="10" value="6" data-suffix=" of 10" class="block h-[28px] w-full cursor-pointer appearance-none bg-transparent focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-[14px] [&::-webkit-slider-runnable-track]:rounded-[3px] [&::-moz-range-track]:h-[14px] [&::-moz-range-track]:rounded-[3px] [&::-webkit-slider-runnable-track]:[background:repeating-linear-gradient(to_right,transparent_0_calc(10%_-_4px),var(--color-dk-bg)_0_10%),linear-gradient(to_right,var(--color-dk-lime)_0_calc((var(--p)_*_9_+_1)_*_10%),var(--color-dk-track)_0)] [&::-moz-range-track]:[background:repeating-linear-gradient(to_right,transparent_0_calc(10%_-_4px),var(--color-dk-bg)_0_10%),linear-gradient(to_right,var(--color-dk-lime)_0_calc((var(--p)_*_9_+_1)_*_10%),var(--color-dk-track)_0)] [&::-webkit-slider-thumb]:-mt-[7px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:h-[28px] [&::-webkit-slider-thumb]:w-[6px] [&::-webkit-slider-thumb]:rounded-[3px] [&::-webkit-slider-thumb]:border-0 [&::-webkit-slider-thumb]:bg-white [&::-webkit-slider-thumb]:shadow-[0_0_0_2px_var(--color-dk-bg)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:h-[28px] [&::-moz-range-thumb]:w-[6px] [&::-moz-range-thumb]:rounded-[3px] [&::-moz-range-thumb]:border-0 [&::-moz-range-thumb]:bg-white [&::-moz-range-thumb]:shadow-[0_0_0_2px_var(--color-dk-bg)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_2px_var(--color-dk-bg),0_0_0_4px_#fff] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_2px_var(--color-dk-bg),0_0_0_4px_#fff]">
</div></div></div>

<div><span class="mb-3 block text-[.72rem] tracking-[.12em] text-[#94a3b8] uppercase">Hue picker</span><div class="rounded-2xl border border-[#1f2a44] bg-dk-bg px-6 pt-[22px] pb-6">
<div class="dk grid gap-3.5 [--p:0]">
  <div class="flex items-baseline justify-between gap-3"><label for="dk-hue" class="text-[.95rem] font-semibold">Accent hue</label><output for="dk-hue" class="inline-flex items-center gap-2 text-[.95rem] font-bold tabular-nums"><span class="size-3.5 rounded bg-[hsl(calc(var(--p)*360)_85%_60%)] shadow-[0_0_0_1px_rgba(255,255,255,.4)]" aria-hidden="true"></span><span class="dk-text">262°</span></output></div>
  <input type="range" id="dk-hue" min="0" max="360" value="262" data-suffix="°" class="block h-[26px] w-full cursor-pointer appearance-none bg-transparent focus-visible:outline-none [&::-webkit-slider-runnable-track]:h-[12px] [&::-webkit-slider-runnable-track]:rounded-full [&::-moz-range-track]:h-[12px] [&::-moz-range-track]:rounded-full [&::-webkit-slider-runnable-track]:bg-[linear-gradient(to_right,hsl(0_85%_60%),hsl(60_85%_60%),hsl(120_85%_60%),hsl(180_85%_60%),hsl(240_85%_60%),hsl(300_85%_60%),hsl(360_85%_60%))] [&::-moz-range-track]:bg-[linear-gradient(to_right,hsl(0_85%_60%),hsl(60_85%_60%),hsl(120_85%_60%),hsl(180_85%_60%),hsl(240_85%_60%),hsl(300_85%_60%),hsl(360_85%_60%))] [&::-webkit-slider-thumb]:-mt-[7px] [&::-webkit-slider-thumb]:appearance-none [&::-webkit-slider-thumb]:box-border [&::-webkit-slider-thumb]:size-[26px] [&::-webkit-slider-thumb]:rounded-full [&::-webkit-slider-thumb]:border-4 [&::-webkit-slider-thumb]:border-white [&::-webkit-slider-thumb]:bg-[hsl(calc(var(--p)*360)_85%_60%)] [&::-webkit-slider-thumb]:shadow-[0_2px_8px_rgba(0,0,0,.5)] [&::-moz-range-thumb]:box-border [&::-moz-range-thumb]:size-[26px] [&::-moz-range-thumb]:rounded-full [&::-moz-range-thumb]:border-4 [&::-moz-range-thumb]:border-white [&::-moz-range-thumb]:bg-[hsl(calc(var(--p)*360)_85%_60%)] [&::-moz-range-thumb]:shadow-[0_2px_8px_rgba(0,0,0,.5)] focus-visible:[&::-webkit-slider-thumb]:shadow-[0_0_0_3px_var(--color-dk-bg),0_0_0_5px_#fff] focus-visible:[&::-moz-range-thumb]:shadow-[0_0_0_3px_var(--color-dk-bg),0_0_0_5px_#fff]">
</div></div></div>
CSS
@theme {
  --color-dk-bg: #121a2e;
  --color-dk-track: #5f6f8a;
  --color-dk-cyan: #22d3ee;
  --color-dk-amber: #fbbf24;
  --color-dk-lime: #a3e635;
}
JavaScript
// Keeps each slider's fill (--p) and its readout in step with the value.
document.querySelectorAll('.dk input[type="range"]').forEach(function (range) {
  var field = range.closest('.dk');
  var out = field.querySelector('.dk-text') || field.querySelector('output');
  function sync() {
    var v = Number(range.value), d = Number(range.dataset.decimals || 0);
    var sign = v < 0 ? '−' : (v > 0 && range.hasAttribute('data-signed') ? '+' : '');
    var text = sign + Math.abs(v).toFixed(d) + (range.dataset.suffix || '');
    field.style.setProperty('--p', (v - range.min) / (range.max - range.min));
    out.textContent = text;
    range.setAttribute('aria-valuetext', text);
  }
  range.addEventListener('input', sync);
  sync();
});

About this set

Four sliders drawn for dark interfaces, where a light theme slider loses its track against the background. Neon glow gives a bass boost control a cyan fill with a soft glow and a white thumb with a halo. Centre zero is a photo editor exposure control from minus 2 to plus 2 EV in tenths, with an amber fill that grows from a tick at zero towards the thumb. LED level splits a fan speed track into ten blocks that light up in lime to the chosen level, and the thumb is a slim white bar that sits inside the last lit block. Hue picker unrolls the colour wheel into the track and fills the thumb and a small swatch with the chosen hue. All are real range inputs on a #121a2e card, and every unfilled track keeps at least 3:1 contrast against it. The LED gaps are painted in the card colour over a quantised fill, and the hue comes from calc(var(–p) * 360) inside hsl(), so a short script only has to set –p and write the value into the output and aria-valuetext.

What’s included

  • Neon, centre-zero, LED and hue variants
  • Unfilled tracks at 3:1 or more on the dark card
  • Centre-zero fill for signed values such as exposure
  • Quantised LED blocks that always line up with the thumb
  • Bootstrap version runs under data-bs-theme="dark"

Accessibility

Every slider has a visible label and a readout, and aria-valuetext carries the formatted value, such as +0.7 EV, 6 of 10 or 262°. Keyboard focus draws a white ring separated from the thumb by a gap in the card colour, so it stays visible on the cyan and amber thumbs. Nothing animates.

Customise it

Change --dk-accent, --dk-track, --dk-bg, --dk-thumb and --dk-h on .dk (plain CSS and Bootstrap); --dk-bg must match the card so the LED gaps and focus gap blend in. In Tailwind edit the --color-dk-* theme colours.