슬라이더

Slider

트랙을 따라 손잡이를 움직여 값 하나(또는 범위)를 고르는 컨트롤.

다른 이름: Range sliderTrack slider
···
html
<div class="sl-wrap">
  <div class="sl-top"><span>볼륨</span><b id="slv">42%</b></div>
  <div class="track" id="trk"><div class="fill" id="fl"></div><div class="thumb" id="th"></div></div>
</div>
css
.sl-wrap{width:min(220px,88%)}
.sl-top{display:flex;justify-content:space-between;font-size:12px;color:var(--muted);margin-bottom:10px}
.sl-top b{color:var(--fg)}
.track{position:relative;height:5px;border-radius:3px;background:var(--line)}
.fill{position:absolute;left:0;top:0;height:100%;width:42%;border-radius:3px;background:var(--accent)}
.thumb{position:absolute;top:50%;left:42%;width:16px;height:16px;border-radius:50%;background:var(--accent);border:3px solid var(--surface);box-shadow:0 1px 4px rgba(0,0,0,.3);transform:translate(-50%,-50%)}
js
const fl = document.getElementById('fl'), th = document.getElementById('th'), slv = document.getElementById('slv'), trk = document.getElementById('trk');
function set(v) { v = Math.max(0, Math.min(100, v)); fl.style.width = v + '%'; th.style.left = v + '%'; slv.textContent = Math.round(v) + '%'; return v; }
set(42);
let auto = true;
function drag(e) {
  auto = false;
  const r = trk.getBoundingClientRect();
  set(((e.clientX - r.left) / r.width) * 100);
}
th.addEventListener('pointerdown', (e) => { auto = false; th.setPointerCapture(e.pointerId); th.addEventListener('pointermove', drag); });
th.addEventListener('pointerup', (e) => th.removeEventListener('pointermove', drag));
let t = 0;
setInterval(() => { if (!auto) return; t += 0.06; set(50 + Math.sin(t) * 45); }, 60);

네이티브 <input type="range">는 키보드(방향키로 값 증감, Home/End로 최소/최대)와 스크린리더 지원을 기본으로 제공하니 커스텀 슬라이더보다 우선 고려할 가치가 있습니다. 직접 만든다면 role="slider"에 aria-valuenow/min/max를 실시간으로 갱신해야 합니다.

스테퍼(숫자 입력)와의 차이는 정밀도입니다. 슬라이더는 "대충 이쯤"을 빠르게 훑을 때 좋고, 스테퍼는 "정확히 37"처럼 정밀한 값이 중요할 때 낫습니다. 볼륨처럼 정확한 숫자가 중요하지 않은 값엔 슬라이더가, 나이·수량처럼 오차가 있으면 안 되는 값엔 숫자 입력이 어울립니다.

프로그레스 바와도 헷갈리기 쉽지만, 프로그레스 바는 시스템이 계산한 값을 사용자가 읽기만 하는 출력이고 슬라이더는 사용자가 값을 바꾸는 입력이라는 점에서 정반대입니다.