連続する数値範囲をドラッグ操作で選択させるコンポーネント。「正確に127を入力したい」場面ではなく、「音量をだいたい70%くらいに」「価格帯を1万〜5万円で」という曖昧さを許容する範囲選択のために存在する。
この記事を読むと、SliderとNumber Input・Selectの使い分け、Range Sliderの設計、キーボード操作とARIA属性の実装基準が自分でできるようになります。
1. UI例(Preview / Live)
実装で見る(GunjoUI)
この部品を、デザインシステム GUNJO の実装で確かめられます。
2. 定義(Definition)
数値の連続した範囲を水平(または垂直)のトラック上でドラッグして選択するコンポーネント。単一値の選択(Single Slider)と最小・最大値の範囲選択(Range Slider)の2種類がある。
Number Inputとの違い:Number Inputは正確な数値を入力する場面に使う。Sliderは「だいたいこの辺」という曖昧な選択を許容する場面——音量・明るさ・価格帯フィルタなど——に使う。
Selectとの違い:Selectは離散した選択肢から1つを選ぶ。Sliderは連続した数値範囲を選ぶ。「S/M/L/XL」のサイズ選択はSelect、「1〜100%の音量」はSlider。
3. 使い分け(When to use / When NOT to use)
3.1 When to use
- 音量・明るさ・再生位置など、だいたいの値で良い連続量の調整
- 価格帯・評価スコアなど、範囲でフィルタリングする場面
- 正確な数値より「感覚的な調整」の方がユーザーにとって自然な入力
3.2 When NOT to use
- 正確な数値が必要な入力(金額・数量・コード値など)→ Number Input を使う
- 離散した選択肢が少数(S/M/L など)→ Select / Radio を使う
- タッチデバイスで正確な操作が困難な小さなスライダー → Number Input やステッパーに切り替える
3.3 代替UI(Alternatives)
- 正確な数値入力 →
Number Input(<input type="number">) - 少数の離散選択肢 →
Select/Radio Button - スライダー+精密入力の組み合わせ → Slider + Number Input の併置(両方向に同期)
4. 設計判断の核(Decision Principles)
「正確な値が必要か、だいたいで良いか」——これだけで Slider か Number Input かが決まる。
判断の優先順位:① 精度要求 → ② 範囲の広さ → ③ 現在値の表示 → ④ キーボード操作性
- Slider を使う場合は常に現在値を数値で表示する(「だいたい70%」ではなく「70%」と明示)
- Range Slider(最小・最大の2ハンドル)は、2つのハンドルが交差しないロジックを実装する
stepを設定して「5刻み」「1000円刻み」など意味のある単位で動くようにする- Slider 単体で精度が不足する場合は、横に Number Input を並置して双方向同期させる
5. 状態設計(States)
5.1 必須状態(Required)
- Default:トラックとハンドル(サム)が視覚的に明確。現在値を表示
- Focus:ハンドルにフォーカスリングを表示(省略不可)
- Disabled:トラックとハンドルをグレーに、
cursor-not-allowed
5.2 条件付き状態(Conditional)
- Hover:ハンドルにシャドウ or サイズ変化でクリッカブルを強調
- Active(ドラッグ中):ハンドルのサイズを大きくしてドラッグ中の視覚的フィードバック
- Error:範囲外の値が入力された場合(Range Sliderで最小 > 最大など)にトラックを赤に
5.3 State Gallery
| 状態 | 必須 | 何を伝えるか |
|---|---|---|
| Default | ✅ | 現在の値と操作可能な範囲 |
| Focus | ✅ | キーボードユーザーに今ハンドルにフォーカスがあることを示す |
| Disabled | ✅ | 現在この値は変更できないこと |
| Hover | — | このハンドルをドラッグできることを強調する |
| Active | — | ドラッグ操作中であることを示す |
6. バリエーション設計(Variants)
Sliderのバリアントは主に「ハンドルの数」と「目盛り・ラベルの有無」で決まる。
| バリアント | 目的 |
|---|---|
| Single Slider | 1つの値を選択(音量・明るさ・再生位置) |
| Range Slider | 最小〜最大の範囲を選択(価格帯・期間フィルタ) |
| With Ticks | 目盛り付き。離散的なステップを示す(0, 25, 50, 75, 100) |
| With Input | Sliderの横にNumber Inputを並置し、精密入力も可能にする |
禁止パターン:Range Sliderで最小ハンドルと最大ハンドルが交差できる設計 → 「最小が最大を超える」という矛盾状態が発生する。
7. パターン集(Good / Bad / How to fix)
7.0 よく崩れる設計パターン(3つ)
- 現在値の非表示:Sliderだけ置いて数値を表示しない → 「今何に設定したか」が分からない
- 精度要求場面での使用:金額や数量の正確な入力にSliderを使う → 1円単位の操作が事実上不可能になる
aria-valuetextの欠落:aria-valuenow="70"だけでは単位が分からず、スクリーンリーダーが「70」としか読まない
7.1 Bad(典型3つ)
- 音量スライダーに現在値表示がなく「今何%か」が分からない
- 価格フィルタをSliderで実装したが
stepが設定されておらず1円単位で動いてしまう <input type="range">のみでARIA属性なし → スクリーンリーダーが値の意味を読み上げられない
7.2 Good(対になる3つ)
- スライダーの右上(または下)に現在値を常時表示し、ドラッグに合わせてリアルタイム更新する
step={1000}を設定し「1,000円刻み」で動くようにする。目盛りで刻みを視覚化するaria-label="音量"+aria-valuenow={70}+aria-valuetext="70パーセント"を組み合わせる
7.3 How to fix(手順)
- Sliderの近くに現在値を数値で常時表示する(ツールチップか固定テキスト)
step属性で意味のある刻み幅を設定するrole="slider"+aria-valuemin+aria-valuemax+aria-valuenow+aria-valuetextを全て付与する- キーボード操作(
←/→で1ステップ、Home/Endで最小・最大)が動作することを確認する
7.4 GUNJO 実装で見る(Bad / Good)
同じ GUNJO の Slider を、ラベル/値表示の崩れた使い方と正しい使い方で対比。
8. ルール(Must / Better)
Must(守らないと壊れる)
Better(品質が跳ねる)
9. アクセシビリティ要件(必須)
Keyboard
Tabでハンドルにフォーカスでき、←/↓で値を減らし→/↑で値を増やせることHomeで最小値、Endで最大値に移動できることPage Up/Page Downで大きなステップの移動(任意)
Focus
- ハンドルのフォーカスリングは周囲と4.5:1以上のコントラストを持つこと
Screen Reader
role="slider"とaria-valuemin/aria-valuemax/aria-valuenowを付与するaria-valuetextで単位付きの読み上げテキストを設定する
<!-- 基本パターン -->
<div
role="slider"
tabindex="0"
aria-label="音量"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="70"
aria-valuetext="70パーセント"
>
<!-- ハンドルのDOM -->
</div>
Touch / Pointer
- ハンドルの視覚的サイズが小さい場合でも、タッチターゲットを44×44px以上確保する
- トラック全体をタップして値をジャンプできるようにする
Contrast / Readability
- トラックと背景は3:1以上のコントラスト比(WCAG 1.4.11 Non-text Contrast)
- ハンドルはトラックに対して視認しやすいコントラストを持つこと
10. 実装メモ(Implementation Notes)
<input type="range">はブラウザのデフォルトスタイルを使えば多くのARIA属性を自動で持つが、見た目のカスタマイズが難しい。Radix UI / shadcn のSliderは ARIA 対応済みかつスタイルカスタマイズが容易- Range Slider(2ハンドル)はHTML標準の
<input type="range">では実装できないため、ライブラリか自前実装が必要 step属性はHTML属性として設定できるが、React ではstep={1000}のようにプロップスで渡す。onChangeの値は文字列で返るためNumber()で変換すること
11. 関連リンク
- 関連するUIデザイン原則: フィードバック (Feedback), アフォーダンス (Affordance), Fittsの法則 (Fitts's Law)
- 用語集(定義): アクセシビリティ (Accessibility), タッチターゲット (Touch Target)
- 関連するUIコンポーネント(横): Button(ボタン), Text Input(テキスト入力)
12. まとめ
Sliderの設計は「正確な値が必要か、だいたいで良いか」という一問から始まります。迷ったら 4. 設計判断の核 に戻り、精度要求を確認してください。Sliderを使うなら現在値の常時表示と aria-valuetext による単位付き読み上げが最低ラインです。精度が必要な場面はNumber Inputへの切り替え、または Slider + Number Input の併置で解決してください。