12周年記念パーティ開催! 2024/5/10(金) 19:00

レンジ入力欄の実装とカスタマイズ 前編 レンジ入力欄の仕様

input要素のtype属性にrangeを指定すると、スライダー、つまり範囲によって数値が入力できるようになります。第1回目では組み合わせて使う属性とともに、実装のための仕様を細かくチェックします。

発行

著者 坂巻 翔大郎 フロントエンド・エンジニア
レンジ入力欄の実装とカスタマイズ シリーズの記事一覧

はじめに

input要素はtype属性値によって、さまざまな見た目、入力方法に変化します。

本記事では、input要素のtype属性値をrangeにした状態である「レンジ入力欄」について解説します。また次回は、スタイルをカスタマイズする方法を取り上げます。

まずは、レンジ入力欄について解説します。

レンジ入力欄とは

レンジ入力欄は、input要素のtype属性値をrangeにすることで作成されます。最新のブラウザであれば、問題なく利用できます。

<input type="range">

レンジ入力欄(<input type="range">)は、サム(thumb)*をつかんで動かし、ざっくりとした数値を指定できます。最大と最小を目安にしながら、どのあたりの数値を設定しているかも直感的に判断することができます。

*注:サム(thumb)

サムとはスライダー上にある「つまみ」のことです。

たとえば、音のボリュームや明るさの調節をするUIのように「だいたいこれくらいかな?」という感じで、感覚的に入力したいものに向いています。

レンジ入力欄以外で数値や数字を扱う入力欄としては、数値(<input type="number">)が挙げられますが、それらは正確な値を入力したい場合に利用します。

レンジ入力欄で指定できる属性

レンジ入力欄には、最小値(min属性)や最大値(max属性)が設定できます。またstep属性を組み合わせることで、最小値から最大値の間の刻みの間隔をコントロールすることができます。実際に使いそうな例をいくつか挙げて解説します。

特に何も指定しない

まずinput要素のtype属性値にrangeを指定しただけの状態を見てみましょう。

range指定のみ

<input type="range">

このレンジ入力欄では、0から100の範囲の数値を指定できます。なぜ最小値が0で、最大値が100であるかは、省略されたmin属性とmax属性の初期値が関係しています。

まず、min属性が省略されているので、最小値は「min属性の初期値である0**」になります。次に、max属性も省略されているので、最大値は「max属性の初期値である100**」となるのです。

仮に<input type="range" min="10">と、min属性だけを指定した場合は、最小値が10で、最大値が100のレンジ入力欄となります。

サムの初期位置は中央になり、0から100の間である50を示す位置になります。つまり、このinput要素のvalue属性の初期値は50となっています。

最小値と最大値を指定する

レンジ入力欄に最小値と最大値を指定するにはmin属性とmax属性を記述します。

min属性とmax属性の指定

<input type="range" min="1" max="5">

min属性値(最小値)に1、max属性値(最大値)に5を指定しました。こうすることで、1から5の5段階評価に使うこともできます。1から5の5段階ですから、サムの初期位置は中央になり、初期値は3となります。

もし最小値を1、最大値を6にした場合、サムの初期位置や初期値はどうなるのでしょうか。

<input type="range" min="1" max="6">

デモを見ると、サムは中央よりも右に位置しており、初期値は4となります。なぜ4なのでしょうか。その理由は後述します。

ステップ数を指定する

入力の際に刻むステップ数はstep属性で指定できます。たとえば、何かの評価をするときに、1から5の範囲で調整したいが、2.5という刻みがほしい、という場合に使えます。

step属性の指定

<input type="range" min="1" max="5" step="0.5">

step属性の初期値は1です。属性値には小数点を指定することができるため、step="0.5"とすれば0.5刻みに、step="0.01"とすれば0.01刻みにできます。

datalist要素で目盛りを表示する

入力候補一覧を作成できるdatalist要素と、レンジ入力欄を組み合わせることができます。組み合わせ例を見てみましょう。

レンジ入力欄とdatalist要素の組み合わせ

<input type="range" list="my-datalist">
<datalist id="my-datalist">
  <option value="0">
  <option value="10">
  <option value="20">
  <option value="30">
  <option value="40">
  <option value="50">
  <option value="60">
  <option value="70">
  <option value="80">
  <option value="90">
  <option value="100">
</datalist>

レンジ入力欄の上に、option要素で指定した分の目盛りとして表示されます。ただし、目盛りの見た目や実装状況は、ブラウザやOSごとに異なります。筆者が確認した環境ではChrome、Edge、IE11で目盛りが表示されました。

レンジ入力欄の初期値が決まる条件

ここまでの説明でmin属性とmax属性の使い方がイメージできるようになりました。次にレンジ入力欄の初期値について考えてみます。

初期値について仕様書には、次のように記述されていました。

デフォルト値は、最小値に最小値と最大値の差の半分を加えたものである。ただし、最大値が最小値よりも小さい場合を除き、この場合デフォルト値が最小値となる。 HTML5日本語訳 4.10.5.1.10 Range状態(type=range)

つまり一般化すると、次のような表現ができます。

min属性とmax属性で初期値を計算

if (max属性値よりもmin属性値が大きい) {
  初期値 = min属性値
} else {
  初期値 = (min属性値 + (max属性値 - min属性値) / 2)
}

ここに、min属性値1、max属性値6を当てはめてみましょう。

<input type="range" min="1" max="6">

初期値の計算

let 初期値
const min = 1
const max = 6

if (max < min) { // ここではmaxのほうがminよりも大きいのでelseへ
  初期値 = min
} else {
  初期値 = ( min + (max - min) / 2 )
  // 初期値 = ( 1 + ( 6 - 1) / 2 )
  // 初期値 = 1 + 2.5
  // 初期値 = 3.5
}

計算上は初期値が3.5になるはずですが、3.5を取ることはできません。というのもstep属性が未指定なので、現在のstep属性値は初期値の1です。すると、取る値は1刻みの値にならなくてはなりません。もっとも近いのは34ですが、この場合は4となります。

仕様書では、次のような記述になっています。

If two numbers match these constraints, then user agents must use the one nearest to positive infinity.

2つの数字がマッチする場合、ユーザーエージェント(ブラウザなど)は、正の無限大(positive infinity)にもっとも近い数字を使わなければならないのですから、2つの数字のうち、より大きい数字を取ることになります。

もしstep属性値が0.5であれば、初期値はそのまま3.5となります。

こういったことから、value属性値が指定されていた場合であっても、指定したmin/max/step属性の値によっては指定したvalue属性値が無視される場合があります。その例を見てみましょう。

<input type="range" min="0" max="100" step="20" value="50">

HTML上では、最小値が0、最大値が100、ステップ数が20、このinputの初期値(value属性値)は50の指定になっています。先ほどの計算式からは初期値は50であると求められます。しかしデモで確認すると指定どおりにはならず、初期値は60です。

ここで初期値が実際に取り得る値を考えてみましょう。0から100の範囲でステップ数が20ですから、0 20 40 60 80 100のどれかの値になります。素直に初期値の50にはなりません。50にもっとも近い値は4060ですが、大きいほうの数字、60が初期値となります。

ここまでのまとめ

今回はinput要素にrangeというtype属性を指定してつくられる「レンジ入力欄」の仕様を解説しました。最小値、最大値の指定や、スライダー(範囲)にステップを設けた場合、初期値(サムの場所)はどのように決定されるかなど、少し細かい知識まで押さえました。

次回はレンジ入力欄の見た目をカスタマイズする方法を解説します。