<input type="range"> でつまみを複数表示する

# はじめに
初投稿です。お手柔らかにお願いします。


# 概要
業務で複数のつまみを持つレンジバーが欲しい、という事態が発生したので、この記事(https://css-tricks.com/multi-thumb-sliders-particular-two-thumb-case/) を参考に実装しました。その備忘録です。

以下のようなものが出来上がります。

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="css,result" data-user="takuya115" data-slug-hash="YzGbapj" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="slidebar-multithumb">
  See the Pen <a href="https://codepen.io/takuya115/pen/YzGbapj">
  slidebar-multithumb</a> by takuya115 (<a href="https://codepen.io/takuya115">@takuya115</a>)
  on <a href="https://codepen.io">CodePen</a>.
</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

なお、実装にあたり非標準の疑似要素を使っています。
**表示の確認にはGoogle Chromeを使っており、ほかのブラウザでは確認していません。**
たぶんFireFoxとかだとうまくいきません。

# 環境(ブラウザ)
Google Chrome バージョン: 88.0.4324.104（Official Build）（64 ビット）


# レンジバーを重ねて表示すればつまみは増える
\<input type="range"> を使うとレンジバーが表示できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437227/0d57b3da-01e9-a94b-9547-bcdfec07eccd.png)

しかしこれにはつまみが1つしかありません。
cssも、非標準の要素を含めても増やす方法はなさそうでした。

ではどうするか。

**2つのレンジバーを重ねてやればつまみが2つあるように見えます。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437227/58188dad-180b-2d91-2d4b-5b72d33b3dff.png)


実装は以下の通り。

``` index.html
<div class="slidebar-multithumb">
    <input class="thumb-1" type="range" name="range-1" id="range-1" value="45" min="0" max="100" step="1">
    <input class="thumb-2" type="range" name="range-2" id="range-2" value="55" min="0" max="100" step="1">
</div>
```

``` style.css
.slidebar-multithumb {
  display: grid;
  padding: 1rem;
}

.slidebar-multithumb input[type="range"] {
  grid-column: 1;
  grid-row: 2;
}

```

ここでは`display: grid;`を使って2つの\<input type="range">を重ねています。

さて、レンジバーを重ねてつまみが2つある風に表示はできました。
しかし問題が2点あります。

- 上側のつまみ(ここではid=range-2の方)しか操作できない
- 下側のつまみが、上側のレンジバーに隠れて見づらい

それを解消していきます。

# 両方のつまみを操作できるようにする
上側のつまみしか操作できないのは、当たり前ですが、重なっているからです。
そこで、cssのpointer-eventsというプロパティを使って、つまみ部分だけ操作できるようにしてやります。

``` style.css
.slidebar-multithumb {
  display: grid;
  padding: 1rem;
}

.slidebar-multithumb input[type="range"] {
  grid-column: 1;
  grid-row: 2;
  /* <input type="range">全体の操作を無効にする */
  pointer-events: none;
}

.slidebar-multithumb ::-webkit-slider-thumb {
  /* つまみ部分を示す疑似要素-webkit-slider-thumbで、つまみだけ操作できるようにする */
  pointer-events: auto;
}
```

これで両方のつまみが操作できるようになりました。

# レンジバーのスタイルを調整する
下側のつまみが見づらいので、あとは見た目を整えてやればOKです。
疑似要素-webkit-slider-thumbと-webkit-slider-runnable-track(レンジバーの溝部分)を使ってスタイルを指定してやります。

``` style.css
/* 色設定 */
:root {
  --bg: rgb(224, 224, 224);
  --bar: rgb(0, 255, 0);
}

.slidebar-multithumb {
  display: grid;
  padding: 1rem;
}

.slidebar-multithumb input[type="range"] {
  grid-column: 1;
  grid-row: 2;
  pointer-events: none;
  /* レンジバーの背景を透明にする */
  -webkit-appearance: none;
  background: none;
  /* わかりやすいのでボーダーつける */
  border: 1px solid;
  /* overflow: hiddenにすると溝に色を付けたとき、その部分が巨大化しない */
  overflow: hidden;
}

.slidebar-multithumb ::-webkit-slider-thumb {
  pointer-events: auto;
  /* つまみ部分を長方形にする */
  -webkit-appearance: none;
  width: 0.8rem;
  height: 1.5rem;
}

/* 最初のつまみを上にする(順番をわかりやすくするため) */
.thumb-1 {
  z-index: 1;
}

/* つまみの溝の背景。thumb-1をnoneにすることで後ろのthumb-2が表示される */
.thumb-1::-webkit-slider-runnable-track {
  background: none;
}

.thumb-2::-webkit-slider-runnable-track {
  background: var(--bg);
}

/* それぞれのつまみの設定。box-shadowでつまみの左側を埋める色を設定できる。 */
.thumb-1::-webkit-slider-thumb {
  background: rgb(255, 139, 139);
  box-shadow: -100vw 0 0 100vw var(--bg);
}

.thumb-2::-webkit-slider-thumb {
  background: rgb(77, 169, 255);
  box-shadow: -100vw 0 0 100vw var(--bar);
}

```

レンジバーの背景を一旦すべてnoneにして、そのあとつまみと溝部分にそれぞれ背景を設定します。これで、つまみとつまみの間に色付きの部分を表示できるようにしています。

参考にした記事では`:after`と`calc()`を使って表示するようにしてましたが、なんとなく複雑だったので採用しませんでした。

ただしこの方法では、下側のthumb-2のつまみが、上側のthumb-1のつまみより左にいくと隠れてしまうので、その辺はJavaScriptとかでよしなにしてやってください(なお参考記事の方法ではそうなりません)

いずれにせよ、これで上で示したような2つのつまみを持つレンジバーが作成できました。
inputタグをそのまま利用しているので、JavaScriptでvalueを取得するときも簡単です。


以上、\<input type="range"> でつまみを複数表示する方法でした。


# 参考
- Multi-Thumb Sliders: Particular Two-Thumb Case | CSS-Tricks
https://css-tricks.com/multi-thumb-sliders-particular-two-thumb-case/

- pointer-events - CSS: カスケーディングスタイルシート | MDN
https://developer.mozilla.org/ja/docs/Web/CSS/pointer-events

- ::-webkit-slider-thumb - CSS: カスケーディングスタイルシート | MDN
https://developer.mozilla.org/ja/docs/Web/CSS/::-webkit-slider-thumb

- ::-webkit-slider-runnable-track - CSS: カスケーディングスタイルシート | MDN
https://developer.mozilla.org/ja/docs/Web/CSS/::-webkit-slider-runnable-track