スライダーのUIデザインをカスタムしたいけれども特定ライブラリのみでは実現できないような場合がある。
そこで本記事では <input> タグをベースとしたHTMLで描画できるスライダーについて様々なデザイン例を紹介する
デザイン例
いずれのスライダーについてもHTMLの基本構造はほぼ同じ。
また2026年時点の主流ブラウザであればいずれも見た目がほぼ統一されることを意識している
01. iOS 風
See the Pen slider01_ios by hrel11 (@hrel11) on CodePen.
今回紹介するスライダーの中でも特に汎用性高く使える。
linear-gradient、 background-size および CSS変数 を併用することで進捗バーの背景色を表現している
02. ニューモーフィズム (Neumorphism)
See the Pen slider02_neumorphism by hrel11 (@hrel11) on CodePen.
背景とつまみの色が同じ。
box-shadow で影を描画しており inset ありで凹、inset なしで凸部分を表現している
03. クレイモーフィズム (Claymorphism)
See the Pen slider03_clay by hrel11 (@hrel11) on CodePen.
box-shadow による演出が重要。
トラックの内側と外側それぞれに影を描画することで特有の立体感が得られる
04. ネオブルータリズム (Neo-Brutalism)
See the Pen slider04_neobrutalism by hrel11 (@hrel11) on CodePen.
角丸やぼかしといった要素が一切排除され、コントラスト比が際立つ
05. モダン・スキュモーフィズム (Modern Skeuomorphism)
See the Pen slider05_skeumorphism by hrel11 (@hrel11) on CodePen.
縦方向の linear-gradient を多段設置することで金属的なハイライトを演出。
つまみ部分には linear-gradient に加えて radial-gradient の光沢を重ねることでさらに立体感を表現している
06. ネオン
See the Pen slider06_neon by hrel11 (@hrel11) on CodePen.
背景色を暗くすることが前提。
トラックやつまみにぼかし成分多めの box-shadow を適用する。
またトラックの塗りとつまみのグローの間で色を揃えることで光が漏れるような表現に近づく
07. セグメント
See the Pen slider07_segment by hrel11 (@hrel11) on CodePen.
repeating-linear-gradient によって区切り線を表現
08. 角丸平行四辺形
See the Pen slider08_skewed by hrel11 (@hrel11) on CodePen.
.slider__body 要素に skewX(-8deg) を適用している。
これによりトラック・つまみ・当たり判定・フォーカスリングまで全て変形する
09. 音量バー
See the Pen slider09_volume by hrel11 (@hrel11) on CodePen.
clip-path によりトラックを三角に切り抜く。
つまみを opacity: 0; で非表示にして塗りの先端部分を操作点として見せる。
またつまみが見えない分、スマートデバイスからのタッチ操作をしやすくするためにつまみの横幅を多めに取ると良い
ポイント
<input> タグ製のスライダーをCSSでスタイリングする際の注意点を列挙する
[1] 擬似要素の網羅
Firefox (Gecko) と Firefox以外 (Blink / WebKit) ではスライダー各部位について擬似要素の名称および挙動が異なる。両系統のスタイルを必ず網羅する
| 部位 | Chrome / Edge / Safari | Firefox |
|---|---|---|
| トラック | ::-webkit-slider-runnable-track |
::-moz-range-track |
| 進捗(左側の塗り) | (無し) | ::-moz-range-progress |
| つまみ | ::-webkit-slider-thumb |
::-moz-range-thumb |
Gecko には進捗部分を示す疑似要素 ::-moz-range-progress が存在するが Blink / WebKit には無い。
そこで「つまみより左を塗りつぶす」表現を普遍的に実現するために以下の手法を利用できる
- JavaScript でスライダーの値を CSS 変数に流す
<div class="slider">
<div class="slider__body">
<div class="slider__track"></div>
<input
class="slider__input"
type="range"
min="0"
max="100"
step="1"
value="50"
/>
</div>
</div>
const slider = document.querySelector(".slider");
const input = slider.querySelector(".slider__input");
const update = () => {
const ratio = (input.value - input.min) / (input.max - input.min);
slider.style.setProperty("--p", ratio);
};
input.addEventListener("input", update);
update();
<input> タグの oninput 属性内にJavaScriptを記述することも可能だがインラインスクリプトの使用はベストプラクティスとは限らない点に注意
- CSP (Content Security Policy) の設定次第で
unsafe-inlineスクリプトの実行がブロックされるため - HTMLとJavaScript間で関心が分離されず可読性や保守性が低下するため
2. トラックの background で描画する(バーの色の境界部分をCSS変数によって制御する)
.slider {
--p: 0.5;
--thumb: 32px;
}
.slider__track {
background:
linear-gradient(to right, #a78bfa, #8b5cf6) no-repeat,
#dfe0fb;
background-size: calc(var(--p) * (100% - var(--thumb)) + var(--thumb) / 2)
100%;
}
[2] リセットCSSの適用
inputタグとその疑似要素群の既定スタイルを上書きするためのCSSを記述する
/* inputタグ */
.slider__input {
appearance: none;
-webkit-appearance: none;
background: transparent;
}
/* つまみ(WebKit) */
.slider__input::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
}
/* つまみ(Gecko) */
.slider__input::-moz-range-thumb {
background: transparent;
border: none;
}
/* トラック(WebKit) */
.slider__input::-webkit-slider-runnable-track {
background: transparent;
}
/* トラック(Gecko) */
.slider__input::-moz-range-track {
background: transparent;
}
/* 進捗(WebKit): 該当擬似要素なし */
/* 進捗(Gecko) */
.slider__input::-moz-range-progress {
background: transparent;
}
Firefox は ::-moz-range-progress でつまみの左側を塗るための機構が存在する。
この色を透明化することでブラウザ間の見た目を統一できる
[3] UIパーツの分離
スライダーの進捗部分などを盛り込む際には <input> とは別の要素として管理する。
<div class="slider">
<div class="slider__body">
<!-- トラック(色塗り部分) -->
<div class="slider__track"></div>
<!-- つまみ部分など -->
<input class="slider__input" type="range" />
</div>
</div>
<input> タグのみで実装するとどうしてもブラウザごとの見た目の差異に悩まされやすい。また修正の融通が利きづらいことも多い
今回は <div> タグで進捗部分を別レイヤーに分離しておりこれによってブラウザ間の見た目を統一しやすくなる。加えて表現の幅も広がる。
ただしトレードオフとして <input> および <div> を含めたアクセシビリティの再設計が必要となる。詳細は5章にて後述するがたとえばフォーカスリングのサイズが見た目と乖離していないかなどを確認する
[4] webkit系とmoz系を分割して定義する
バニラCSSでセレクタを記載する場合、接頭辞の異なる疑似要素を1つのセレクタにまとめるとセレクタ全体が無効化されてしまうことがある
/* NG: 接頭辞の違う擬似要素を1つにまとめると、ルール全体が無効化される */
.slider::-webkit-slider-thumb,
.slider::-moz-range-thumb {
/* ... */
}
/* OK: 別々に書く(同じ接頭辞同士ならまとめてOK) */
.slider::-webkit-slider-thumb {
/* ... */
}
.slider::-moz-range-thumb {
/* ... */
}
これはカンマ区切りのセレクタリストにおいてブラウザによって解釈不能であるようなセレクタが1つでも存在するとルール全体が破棄されてしまうためである。
Gecko は ::-webkit-* を解釈できず Blink / WebKit は ::-moz-* を解釈できないためこれらをカンマ区切りでまとめて書かないようにすること
接頭辞が同じ疑似要素はまとめて記述してもOK
ex. -moz-range-track と -moz-range-progress
セレクタ全体が無効化される問題について
:is() や :where() などの一部の疑似クラス関数には forgiving selector list という仕組みがある。これにより不正なセレクタを個別に無視することができる。
※ ただし疑似要素は:is() や :where() の引数には入れられないため、今回のようなスライダーUIの疑似要素についてはこの手段が通用しない
このように2026年現在のCSSでは「セレクタ全体が無効化される」もしくは「されない」ケースが混在するため要注意である。
なおTailwindCSSを利用する場合には複数セレクタを表現する機会はないため本項について特に意識する必要は無い
[5] アクセシビリティの担保
<input> タグの利用
- 大前提としてスライダー実装の際に
<input type="range">を使う - これだけでキーボード操作(←→・Home/End など)と支援技術対応をサポートできる
フォーカスの可視化
フォーカスリングはtabキーを押すことなどで表示される。
実装の際には appearance: none によりフォーカスリングが消えやすいので明示的に補う
.slider__input:focus-visible {
outline: 2px solid #007bff;
outline-offset: 2px;
}
コントラストの確保
UIを自前装飾する場合、視認性を確保するための目安としてトラック・つまみと背景のコントラスト比を WCAG 基準 で確認する
隣接した色との間で少なくとも 3:1 のコントラスト比がある
ただしニューモーフィズムなどどうしてもコントラスト比が出ないUIデザインも存在する。必要に応じてフォールバック表示の実装も検討する
判定の確保
タッチターゲットとしてつまみ部分に対して十分なサイズを確保する。
例として09.音量バーのスライダーでは判定が見た目より広く取られていることで扱いやすくなっている。必ずしも当たり判定を見た目通りにする必要は無い
まとめ
2026年8月現在、スライダーの仕様はブラウザ間で統一されきっていない。そのためスライダーの形・サイズ・目盛りまで作り込む場合には「擬似要素のエンジン差」「つまみの描画位置」「アクセシビリティ」などの観点に注意が必要でありブラウザごとの動作確認も避けられない。本記事がその工数削減と事故防止に寄与できれば幸いである




