RSS Twitter Facebook

2017/12/30 (2017年12月 のアーカイブ)

input type=range タグをカスタマイズするために


これなんですが : 


大晦日なんですけどね。 input-knobs.js というライブラリを作ったりして、ちょっとこの HTML の <input type="range"/> タグという奴と格闘していました。タグ1つで連続値を入力するスライダーが書けるのでとにかく便利。個人的に HTML5 で追加されてよかったタグ第一位くらいに位置するのですが...。

ただ、見た目がね。かなりカオスな事になっています。

現状、シンプルに <input type="range"/> と書いた時に表示されるものが下の図です。興味深いです。Macの方はそれなりに統制が取れているんですけどね。ことデザインに関しては Apple に真っ向から盾突くわけにも行かないとかいう事情があるんですかね? 経緯は知りませんけどみんな Apple の Safari に寄せて来てるんですか? 一方 Win の方はみんな自由すぎ。そもそもの MS Edge が一番浮いてるんじゃないですか。ちょっと癖が強すぎ。ここであまり個性は出してほしくないなぁ。

更に Edge の場合はスライダーの操作中だけ数値が表示されます。これはすごく便利ではあるのだけど Edge でしか表示されないのでこれに頼るわけにも行かないのが現状です。結局数値を読み取る必要がある場合には別の場所に表示する事になります。


という事で検索すれば、この<input type="range"/>タグをスタイルシートでカスタマイズする的な情報もちらほらあるのですが、単発のサンプルだけでは中身がよくわからないので、スライダーを構成している各部品がどうなっているのかをちょっとまとめておきます。


このスライダー全体を指すためのCSSのセレクタは input[type=range] とかで指定できるのですが、詳細なカスタマイズをするには背景やツマミなどスライダー内の各パーツに対してスタイルを適用する必要があります。ボタンのスタイリング等で良く使う :hover や :active 等がエレメント全体の特殊な状態を指す「疑似クラス」と呼ばれるのに対し、このエレメント内の一部分は「疑似要素」と呼ばれ、コロン2つに続くセレクタを使用します。

ただブラウザによって実装が違うので割と面倒です。
取りあえずクロスブラウザで同じ表示になるようなスライダーの背景とツマミ部分の塗りを指定するために必要な情報を考えます。

Chromeの場合:



webkit系 の場合はカスタマイズをする際にまず エレメント本体である input[type=range] と ツマミ部分の ::-webkit-slider-thumb に対して -webkit-appearance:none; を追加してブラウザが独自の描画をするのを止めてから各種の指定をする必要があります。
またこの両方を指定するとエレメントが高さを失いますので height を明示的に指定する必要があります。

::-webkit-slider-runnable-track はエレメント全体の外形と重なっていますが存在するだけで描画にはつかわれていません。

Firefoxの場合:


Firefox にもブラウザの独自描画を止めるための -moz-appearance:none; という CSS の指定があります。ただしこれは明示的に指定しなくても、エレメントの background-color や border をいじった時点で自動的に解除されるようです。

::-moz-range-track がスライダーの溝部分の表示に使われていますが、不要な場合、 display:none; を指定しても消えません。height:0; か opacity:0; ならこれを消す事ができます。

また、Firefox ではツマミ部分にデフォルトで border と border-radius が付いていますので表示を合わせるにはこの辺も指定が必要です。

Edgeの場合:


結構ごちゃごちゃしていますけど、エレメント本体 input[type=range] に対して ::-webkit-appearance:none; を指定すると ::-ms-track、::-ms-fill-lower、::ms-fill-upper がまとめて表示されなく(存在はしているが透明に)なります。
間違いではなく、「-webkit-appearance:none;」です。このブラウザプリフィックスを騙るような事をするのはどうかと思わなくもないのだけど勢力図的にやむにやまれず、という奴でしょうね。

更にツマミ部分も ::-ms-thumb だけでなく ::-webkit-slider-thumb でアクセスできるようになっているので、結果的に -webkit-appearance:none; が指定されている webkit 向けのカスタマイズコードが完全にとは言いませんが割合それっぽく見えるという事になります。

なお、::-ms-tooltip 部分はいらないなら display:none; を使って別途消す必要があります。このツールチップは、display:none; 以外の色指定やサイズ指定等は全く効かないようです。


さて、以上を踏まえて、クロスブラウザで同じ表示になるスタイルシートを作ります。

  input[type=range] {
    -webkit-appearance:none;
    background:#000;
    height:24px;
    width:240px;
    border-radius:8px;
  }
  input[type=range]::-webkit-slider-thumb{
    -webkit-appearance:none;
    background:#f00;
    height:20px;
    width:20px;
    border-radius:50%;
  }
  input[type=range]::-ms-tooltip{
    display:none;
  }
  input[type=range]::-moz-range-track{
    height:0;
  }
  input[type=range]::-moz-range-thumb{
    background:#f00;
    height:20px;
    width:20px;
    border:none;
    border-radius:50%;
  }


どうでしょうか、せっかくなのでちょっと角を丸めたりしています。
こんな感じになっているはずなんですが
画像
実際のタグ

更に...

疑似要素が厄介な所として、複数を並列しては書けないので冗長な感じになってしまいますがしょうがないですね。それに HTML 内でインラインで書く事はできないし、Javascript から element.style.xxx の様なアクセスもできません。

インラインのスタイル指定で疑似要素にアクセスする方法は10年ほど前に提案されていた案があったようなんですが日の目を見る事なく削除されてしまったようです。

クラスや id を振っておいてスタイルシート内のリテラルでカスタマイズするのは問題なくできるのですが、Javascript でこの辺を扱うライブラリを作ろうとすると非常にやりにくいです。結局要素のインスタンス毎に疑似要素の個別スタイルを与えようとすると id を振っておいてグローバルな場所で id 毎にルールを作るような事しかできません。

CSS 内で変数が使える CSS Variables がちゃんと動くようになればもう少し融通が利くようになるのですが、これまた一部のブラウザ上でまだバギーなふるまいがあって今の所まだ実用的じゃなかったりします。もう少しだよ、もう少し。

Posted by g200kg : 2017/12/30 16:08:01