フーノページ


input type = range CSS

input type=rangeをCSSでカスタマイズ。










syntax。

「「3/*Chrome/Safari/Edge*/」」
elm::-webkit-slider-runnable-track {....}
elm::-webkit-slider-thumb {....}

「「3/*Firefox*/」」
#elm::-moz-range-track {....}
elm::-moz-range-thumb {....}


3つの手順が必要。


こんにちは、「ふ」です。
以前の記事で紹介した、input-type = range。
デフォルトのままでも使えるのですが、サイトの雰囲気に合わせて見た目をカスタマイズしたい。そんなケースもあるかと思います。

しかしながら、rangeにCSSを施すのはササッとはいきません。


input type = "range" の構成。

input type = "range"はつまみ部分(thumb)とレール部分(track)から構成されています。
これらの部品にアクセスするには、擬似要素の記述が必要です。加えて、主要ブラウザ(Chrome/Safari/Edge/Firefox)に対応させるためには、ベンダープレフィックスも使っていきます。

またrange自体には「デフォルトCSS」なるものが施されており、これをキャンセルさせないとCSSによる指定を受け付けてくれません。

・デフォルトCSSの解除
・擬似要素を使ったアクセス
・ブラウザに合わせたベンダープレフィックス

やることが沢山あって大変なのですが、今回は4つの主要ブラウザでのプレビューを示しながら、rangeのCSS処理についてじっくりと解説していきます。
自由にカスタマイズできるようになりましょう。

JavaScript、スライダーに応じて要素を変化させる。

〽️ input type = "range"

range要素の仕組みや使い方については、以前の記事⬆︎を参考にしてください。

selectorの記述。


「range」というのは、input要素のtype属性に指定された値です。
HTMLファイル内には「input type = "button"」などのように、ほかのtype属性を持ったinput要素も存在するかもしれません。

いくつか配置されているinput要素の中から、type属性が「range」のもののみをセレクトするには、属性セレクタを使用します。

<input type = "range">
<input type = "button" value = "ボタン">

⬆︎の2つのinput要素。
角括弧[ ]をつかい、属性を限定してセレクトします。

input[type = "range"] {
    「「3/*内容*/」」
}

これでtype属性が「range」のものだけにアクセスして指定することができます。
..が。

めんどくさい。

属性セレクタを使うのも面倒なので、classやidでアクセスしたほうが楽ちん。

<input type = "range" class = 「「5"range1"」」>
<input type = "button" value = "ボタン">
「「5.range1」」 {
    「「3/*内容*/」」
}

フツーにこうしてもちゃんとアクセスできます。なるべくわかりやすいほうが良いですよね。

デフォルトCSSの解除。


<input type = "range" class = "range1">

これはChromeでrangeを表示させたもの。
何もしていないのに、あらかじめ青色がついています。

rangeを作成すると、ブラウザ側で自動的に色や形状などのstyle情報が指定されているのです。このようにブラウザ側で自動的に施されるstyle情報は、デフォルトCSSと呼ばれています。

ブラウザ別の状態。



主要ブラウザでの、rangeのデフォルト状態です。見た目が少しずつ違っています。
ブラウザそれぞれで、rangeにデフォルトCSSが施されていることがわかります。

このデフォルトCSSが効いた状態では、スタイルを自由に上書きすることはできません。試しに背景色を指定してみます。

.range1 {
    background-color:yellow;
}



背景色を指定したのですが、変化がありません。
デフォルトCSSを解除しましょう。解除するには「appearance:none」を指定します。

.range1 {
    appearance:none;
}



これでデフォルトCSSが解除されました。
結果⬆︎を見てみると、thumbの部分は各ブラウザで固有の装飾が残っています。range本体のデフォルトCSSを解除したとしても、thumb単品に対してまた別のデフォルトCSSが施されているのです。
また、すべてのブラウザにおいてtrackが非表示になってしまっています。これものちほど、カスタマイズしていきましょう。

ともあれ、これでrange全体はカスタマイズできるようになりました。

.range1 {
    appearance:none;
    background-color:yellow;
}



そのうえで背景色を指定すると、ちゃんと反映されました。




デフォルトCSS解除後の状態。




このあとのスタイリング時に困惑しないように、デフォルトCSSが解除されたときの「thumb」「track」「range全体」の状態を確認しておきます。

thumb(つまみ)

※ デフォルトCSSがまだ掛かっている。
    width:16px;
    height:16px;
    border-radius:50%;
    background-color:ブラウザに依る

前述のとおり、thumb単品にはまだデフォルトCSSが掛けられています。のちほど解除することにしましょう。
現時点〜デフォルトCSSが掛けられている状態では、幅/高さが16pxで、背景色に関してはブラウザごとに異なる色が与えられています。またborder-radiusを使って、もともとは長方形であるものが円形に装飾されています。

track(レール)

    width:100%
    height:0%
    border-radius:0
    background-color:transparent

thumbのレールとなるtrack。
これについては親であるrangeのデフォルトCSSが解除されると、trackのデフォルトCSSも自動的に解除されます。
解除された状態ではwidthは100%ですが、heightは0で背景色も透過されます。解除後にtrackが非表示になっていたのはこのためです。またborder-radiusも0となります。解除前はデフォルトCSSによって角丸が付いていたのです。

input type = "range"

background-color:#fff
height:指定なし
width:129px

range全体の状態ですが、デフォルトCSS解除後は背景色が白になります。

rangeの親要素に背景色をつけることで、確認できます。
また、heightは指定なしの状態。←というのは、

<div></div>

のように、何も入っていない親要素のようなものです。
thumbのデフォルトCSSがheight:16pxとなっているため、そのぶんだけ領域が確保されています。
widthは129pxでした。これは解除前と変わりません。




trackをカスタマイズ。


    width:100%
    height:0%
    border-radius:0
    background-color:transparent

ではtrackのカスタマイズからやってみましょう。
現状はheightが0、background-colorもtransparentなので、非表示の状態です。高さと背景色をつけて、目に見えるようにしたい。

が、その前に、

親rangeのheightを明示せよ。

親rangeのheight、指定なしの状態では内部要素に応じて領域を確保する、というものでした。
その状態のままtrackのheightを広げていくと、0〜16pxまでは上に広がっていき、それ以上は下に広がっていく、という謎の動きをします。これでは隣接要素とのレイアウトがうまくいきそうにありません。

一方親rangeのheightを具体的に明示してやると、trackのheightはrange領域の中央から徐々に広がってくれるようになります。trackやthumbのカスタマイズに関しては、前提として親rangeのheightを明示してやるようにしましょう。

.range1 {
        appearance:none;
        height:50px;
        background-color:#FFF0CA;
    }    

親rangeのheightを明示し、trackの様子が観察しやすいよう、背景色をつけておきました。




擬似要素とベンダープレフィックス。

お待たせしました。trackにCSSを施していきましょう。さしあたって表示させるには、背景色と高さをつけてやらなければいけません。

trackには擬似要素とベンダープレフィックスの両方を使ってアクセスする必要があります。Chrome/Safari/Edgeには-webkit-、Firefoxには-moz-を使います。

「「3/*Chrome,Safari,Edge*/」」
.range1「「1::-webkit-slider-runnable-track」」 {
        background:gray;
        height:5px;
    }
    
「「3/*Firefox*/」」
 .range1「「1::-moz-range-track」」 {
        background-color:gray;
        height:5px;
    }



あれ?trackは表示できたものの、thumbがぶら下がっているようになってしまいました。
これはthumbがtrackに対して、小要素のようなふるまいをするためです。通常、小要素は親領域に対して上から順に配置されていきます。

試しにtrackの高さをthumbの16px(デフォルトCSSによって指定されている大きさ)よりも大きくしてみましょう。

「「3/*Chrome,Safari,Edge*/」」
.range1::-webkit-slider-runnable-track {
        background:gray;
        height:25px;
    }
    
「「3/*Firefox*/」」
 .range1::-moz-range-track {
        background-color:gray;
        height:25px;
    }

trackの高さを25pxにしてみました。
やはりthumbは親要素的存在である、trackの1ばん上にへばりつくように配置されます。そして大きさは16pxを保持したままです。
ちなみにFirefoxに関しては「thumbのぶら下がり」は発生しません。ちゃんとtrackの中央に位置してくれています。ブラウザ側で自動的に調整されているもよう。

width指定が効かない!

またwidthですが、こちらは指定しても変化してくれません。100%で固定されているようです。
親rangeの領域に対してtrackを小さく表示したい場合は、余白指定を使いましょう。

.range1::-webkit-slider-runnable-track {
        background:gray;
        height:25px;
        margin:10%;
    }
    
 .range1::-moz-range-track {
        background-color:gray;
        height:25px;
        margin:10%;
    }


trackにmargin:10%を指定しました。水平方向に親rangeの10%の余白、垂直方向についてはtrackのheightが優先され「可能な限りの余白」となっています。親要素に対して垂直方向に余白を取りたい場合は、そもそもheightで調整できるので問題ありません。

ちなみにこの余白を取る作業、親range側のpaddingで対応すると、range領域自体の大きさが変わってしまいます。小要素であるtrack側にmarginを指定したほうがバランスを崩さずに済みます。

border-radius。

デフォルトCSS解除後、trackのborder-radiusは0になってしまっています。現在heightは25pxにしているので、半分の12.5pxに指定してみましょう。

.range1::-webkit-slider-runnable-track {
        background:gray;
        height:25px;
        margin:10%;
        border-radius:12.5px;
    }
    
 .range1::-moz-range-track {
        background-color:gray;
        height:25px;
        margin:10%;
        border-radius:12.5px;
    }



絆創膏のようになりました。
trackはこのへんにして、次。thumbをカスタマイズしていきましょう。




thumbのカスタマイズ。


何度かお伝えしたように、webkitのthumbにはそれ自体にデフォルトCSSがかけられています。親rangeのときと同様、解除してやらないとスタイリングを受け付けてくれません。

thumbの様子がわかりやすいよう、trackをシンプルな状態に戻しました。heightを5pxとし、border-radiusやmarginは初期値に戻してあります。
この状態で、webkit(Chrome/Edge/Safari)のデフォルトCSSを解除してみます。アクセスには擬似要素の-webkit-slider-thumbを使用します。

#range1::-webkit-slider-thumb {
        appearance:none;
    }



お。
thumbが表示されなくなってしまいました。デフォ解除後の状態を確認してみましょう。

デフォ解除後のthumb(Chrome、Safari、Edge)。

width:100%;
height:0;
background-color:transparent;
border-radius:none;

trackのときと同じく、高さが0で背景色も透過されています。
非表示になったのはこのためですね。

また解除後のheightは100%となっていて、これは親代わりのtrackに対しての値です。
なのでカスタマイズの際にはwidthを具体的に指定してやらないと、thumbがtrackの幅いっぱいに広がってしまいます。

Firefoxはどーなってる?

Firefoxのthumbについては、デフォルトCSSによる束縛はありません。
親rangeのデフォルトCSSを解除したときに、ブラウザ独自の初期値が指定される、という形です。
よってそのままCSS指定を反映させることができます。現在の状態を見ておきましょう。

width:13px;
height:13px;
background-color:#999;
border:(おおよそ)6.5px f0f0f0 
border-radius:(おおよそ)1.4px

他のブラウザのものとかなり違いますね。
width/heightが具体的に決められ、border-radiusで角丸に加工されています。そのままの見た目でも使えるような状態に初期値が定められています。

またborderで装飾されているという点もおぼえておいて下さい。4つのブラウザでの見た目を厳密に統一したいときには、このプロパティにも配慮することになります。

それではthumbカスタマイズ、いきましょう。webkitとmozの見た目を統一させる方向で進めていきます。
Firefoxのthumbにアクセスするには、擬似要素-moz-range-thumbを使用します。

.range1::-webkit-slider-thumb {
        appearance:none;
        background-color:crimson;
        width:15px;「「1 ..@1@」」
        height:15px;
        border-radius:50%;「「1 ..@2@」」
    }
    
 .range1::-moz-range-thumb {
        background-color:crimson;
        width:15px;
        height:15px;
        border-radius:50%;
        border:none;「「1..@3@」」
    }

@1@ webkit側ですが、デフォ解除後のthumbのwidthは100%となっていました。heightに加えて、widthも具体的に指定しましょう。

@2@ そういえばwebkitのborder-radiusは0でした。Firefoxに合わせるためには丸くしてやる必要があります。

@3@ 一方でFirefox側の調整。thumbには初期値でborderが付けられていたので、これをキャンセルしておきます。


ひとまづ、thumbの見た目が統一されました。
もちろんお好みで、全てにborderを装飾したり、四角いthumbにすることもできます。

扨(さて)あとはwebkitの「ぶら下がり問題」について、対策が必要です。

trackの中央に位置させる。


現状ではthumbのサイズを変化させても、常にぶら下がったままの状態です。
なので作戦を立てました。

@1@thumbのheightをtrackのheightに揃える。
@2@transform:scale()を使い、好きな大きさに拡大。


はじめにthumbの高さをtrackのものと同じにします。すると、相変わらずぶら下がってはいるのですが、見た目上はtrackの中央にthumbが位置しているようになります。


そのうえで、transform:scale( )で好きな大きさに拡大縮小させましょう。transformの基準点は要素の中央となっているので、ぶら下がることなくその場で拡大/縮小してくれます。よってサイズを変化させてもthumbは常にtrackの中央に位置させておくことができます。

.range1::-webkit-slider-thumb {
        appearance:none;
        background-color:crimson;
        「「1width:5px;
        height:5px;」」
        border-radius:50%;
    }
    
 .range1::-moz-range-thumb {
        background-color:crimson;
        「「1width:5px;
        height:5px;」」
        border-radius:50%;
        border:none;
    }

以前指定したtrackのheightは、5pxでした。そこに合わせていきます。なお、thumbの幅と高さを同じにしたかったので、widthもtrackのheightと同じにしています。

ここで「trackと同じ高さにするなら、height:100%としてもいいのでは?」となる方もいるでしょう。が、これはうまくいきません。



理由は相対値指定の場合、webkitとmozでは基準となる対象が違っているからです。
webkitではtrackの高さを100%として算出されるのですが、mozの場合は親rangeの高さを100%として描画されてしまうのです。少し面倒かもしれませんが、trackのheight値を確認して、pxなどの絶対値で指定するようにしましょう。

thumbをtrackのheightと同じにしました。
見た目はセンターに位置している状態。ここから、thumbの中心を起点に、スケールチェンジさせましょう。

.range1::-webkit-slider-thumb {
        appearance:none;
        background-color:crimson;
        width:5px;
        height:5px;
        border-radius:50%;
        「「1transform:scale(4)」」;
    }
    
 .range1::-moz-range-thumb {
        background-color:crimson;
        width:5px;
        height:5px;
        border-radius:50%;
        border:none;
        「「1transform:scale(4)」」;
    }


thumbの中心を起点に拡大させることができました。
これで「ぶら下がり問題」も解決です。

実例サンプル。


ややこしい解説が続きましたが、これでrangeを自由にカスタマイズしていくことができます。デフォルトCSS解除後の状態をちゃんと理解しておくことがうまくスタイリングするコツですね。

カスタマイズしてみたものを2つほど、紹介します。



音響ミキサーのフェーダー風にしてみました。
以下、コードです。

<input id = "rangeA" type = "range">
    #rangeA {
        appearance:none;
        height:65px;
        background-color:#fff;
        width:50%;
        border:solid 1px #bbb;
    }
    
    #rangeA::-webkit-slider-runnable-track {
       background-color:#999;
        height:5px;
        margin:10%;
    }
    
     #rangeA::-moz-range-track {
         background-color:#999;
        height:5px;
        margin:10%;
    }
    
    #rangeA::-webkit-slider-thumb {
        appearance:none;
        background-color:#999;
        height:5px;
        width:2.5px;
        transform:scale(8);
        filter:drop-shadow(0.1px 0.1px 0.2px gray);
        border-left:solid 1px #fff;
        border-right:solid 1px #fff;
    }
    
    #rangeA::-moz-range-thumb {
        background-color:#999;
        height:5px;
        width:0.5px;
        transform:scale(8);
        filter:drop-shadow(0.1px 0.1px 0.2px gray);
        border-radius:0;
        border:none;
        border-left:solid 1px #fff;
        border-right:solid 1px #fff;
    }

thumbのborderですが、webkitは要素の内側に描画されるのに対し、mozでは要素の外側に描画されます。そのため双方の環境において、thumb自体の大きさを調整する必要があります。






trackの背景色をグラデーションにしてみました。
温度計のよう?明るさ調整のスライダーに使えそうですね。

<input id = "rangeB" type = "range">
#rangeB {
        appearance:none;
        width:50%;
        height:20px;
    }
    
    #rangeB::-webkit-slider-runnable-track {
        height:20px;
        background:linear-gradient(90deg,#fff,coral);
        border-radius:5px;
    }
    
    #rangeB::-webkit-slider-thumb {
        appearance:none;
        width:20px;
        height:20px;
        border-radius:50%;
        background:#fff;
        border:solid 2px coral;
    }
    
    #rangeB::-moz-range-track {
        height:20px;
        background:linear-gradient(90deg,#fff,coral);
        border-radius:5px;
    }
    
    #rangeB::-moz-range-thumb {
        width:16px;
        height:16px;
        border-radius:50%;
        background:#fff;
        border:solid 2px coral;
    }

作成の際には各ブラウザでプレビューしながら、カスタマイズを進めて下さい。

今回の調査にあたり、CSS職人ではない「ふ」はとても苦労しました。
CSSって難しい!むしろSVGとJsで作ったほうが後々楽なのでは..?などと思いつつ、記事を終わりたいと思います。

最後までお読みくださり、ありがとうございました。
ではまた〜 🎶


「ふ」です。

ふ

ベクターグラフィック、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。