selectタグのスタイルをcssで整える方法と考察(IE7,IE8,IE9,IE10,~他モダンブラウザ)
<select>のスタイリング(CSS)の記述とその内容について、記事にできるだけまとめました。調べる限り、たぶんみんな苦しんで、そして諦めていったんじゃなかろうか、と感じたので、ある一定までブレイクスルーできたかと思います。
いまだに、IE7だのIE8だのの対応をしなければいけないことを、残念に思いながら。。。
結論のソースを先に。
■HTML
<div class="input-type-select">
<select>
<option>[*テキスト1*]をお選びください</option>
<option>[バリュー1]</option>
<option>[バリュー2]</option>
<option>[バリュー3]</option>
</select>
</div>
■CSS
div.input-type-select{
vertical-align:top;
display:inline-block;
max-width:490px;
box-sizing:border-box;
overflow:hidden;
border-top:1px solid #ccc;
border-right:2px solid #ccc;
border-bottom:2px solid #8E8E8E;
border-left:1px solid #ccc;
border-radius:5px;
background:#FAF6F5 url("bg.png") no-repeat right center;
position:relative;z-index:3;}
div.input-type-select select{
text-overflow:ellipsis;
box-sizing:border-box;
width:518px;
width:calc(100%);
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding:3px 35px 3px 5px;
background:transparent;
border:none;
border-radius:4px 3px 3px 4px;
font-size:14px;font-size:1.4rem;line-height:1.5em;color:#333;font-family: Meiryo,"メイリオ","Hiragino Kaku Gothic Pro","ヒラギノ角ゴ Pro W3",Helvetica,sans-serif;
white-space:normal;
position:relative;z-index:-2;}
div.input-type-select select::-ms-expand {display:none;}
div.input-type-select select option{background:#FAF6F5;}
div.input-type-select select:focus option{background:#fff;}
div.input-type-select:after{
content:"";display:block;width:10px;height:100%;
position:absolute;right:23px;top:0;z-index:10;
background:#FAF6F5 url("bg.png") no-repeat left center;}
div.input-type-select::after{
content:"";display:block;width:19px;height:100%;
position:absolute;right:35px;top:0;z-index:10;
background:#FAF6F5;
transform:rotate3d(1,1,0,180deg);
transform-origin: 0 150px;
-webkit-transform:rotate3d(1,1,0,180deg);
-webkit-transform-origin: 0 150px;}
*+html div.input-type-select{background:none;border:none;}
*+html div.input-type-select select{width:100%;background:#FAF6F5;padding:0;}
■firefoxにてキャプチャ(一番の理想に近いもの)
■IE8(エミュでキャプチャしたので、ちょいずれてるが。実機ではOK。)
なぜこんな記事を書こうと思ったのか
Webで調査した(調べ方がよくないのかもしれない)が、みんな<select>のスタイリングの可能性を、どうも途中でとめているようだ。
可能性、、というよりは、社会不適合ブラウザの対応・・といった方が正しそうだが。
かくいう私も、現時点で完璧にやり切れたかといわれると、たしかに、細かいところを突かれると、HTMLとCSSだけでは、実現できなかった部分がある。これについては、すでにソースを分析し終えた方であれば、その理由がわかるはずであるし、本文の後の方で反省として残しておこうと思う。
当然だが、"こんな"記事は、すなわちビジネスの決済をしているようなお偉い方々や、そもそもあなたの同僚にさえ、まったく理解ができないかもしれないし、価値も見いだせないかもしれない。
だからこそ、このように文明の発達を阻害するブラウザのために、わざわざあなたの貴重な時間を使ってほしくないと願い、今にいたる。
未来の可能性がまだまだある20代の方々などには、特に、この負の遺産ブラウザへの対応をする時間は、とりわけ"労害のための会議"に付き合うようなものであり、モチベーションなどあるはずもない。
何かの助けや参考になれば幸いである。
色々な制限を先に
<option>だ。
こいつは、もう次元の違う強さを持っている。ブラウザをはみ出すのだ。
手の付けようがない。結局こいつをちゃんと操作することはできなかった。
ただし背景色を付けたりすることくらいはできる。
<select>のafter,before。
selectにafter,beforeが使えたら、どんなに楽だったか今でも残念。
まあ早い段階で心の切り替えしができた。
<select>の矢印ボタン。
基本的に、矢印ボタンは、いる。しかもIE8,9あたりは、消せない。
↑こういうやつ。
selectのスタイリングは、こいつとの向き合いが全ての勝負である。
ただし、単純にないがしろにもできない。この矢印部分の存在は、配下のoptionを開くという認知的機能(メンタルモデルというか、アフォーダンスというか、シグニファイアというか)が提供されるため、いってみれば、なくてはならない。
したがって色形を変更す際にも、UIデザインとしては、必須であり位置もそうそう替えられないものであるがゆえに、考えることは多い。
validでa11y的にも問題がないようにする。
HTML/CSSともにきれいなコードにし、設計もちゃんとする。
option選択時、option選択後、の表示にも気を遣う。
前述したとおり、option自体はブラウザを超える表示になるため、操作不能だとしても、多少なりのケアは必要。
例えば上記矢印部分を右側にoverflowさせるサンプル例を見るが、%で飛ばすと、コンテンツ幅(テキスト量)の割合なので、削る部分がどれくらいか操作できなくなる。
さらに、option選択時、selectの幅であろう部分より飛び出てしまう。
ちょっと不細工であること(まぁ、そもそも最大幅以上の文字があると同じようになるのだが)と、選択後、
作成されるであろう背景モノに被るため、よろしくない、という結論。
ソースの説明
DOMは説明するまでもないだろうと思う。
一応補足すると、特にdivじゃなくていい。今この場で文書構造の説明をする気もないのでdivにした。少し悔しかったのは、何か一枚ないとレイアウトすらさせてくれなかったことくらいか。
したがって、以後はCSSの説明を。
■div.input-type-select{~
外側のスタイルを指定している。どっかに置く場所によってちょこちょこ変えてくれればそれでいいかと。かなり一般的な内容だと思うので、必要分だけ説明。しいて言えば、このくらいの大きさの背景画像ならdata形式にすることをお勧めする。コンポーネント数の削減はパフォーマンスを向上させる。
z-indexは、社会的損失であるIE8の対応。
max-widthは、optionの特性で横にはみ出させようと<select>に働きかけるらしくそれの予防。値はレイアウトによって入れ替える。
■div.input-type-select select{
こいつが一番の肝。
text-overflow:ellipsis; ←できれば、はみ出そうとする要素を3点リーダ
box-sizing:border-box; ←widthの計算式を楽にするため
width:518px; ←存在価値のないIE8のための記述(結局IE8はマックスまでいく必要がある。)
width:calc(100%); ←Webの発展を阻害するIE9以降の幅で上書き
-webkit-appearance: none; ←selectの矢印消し
-moz-appearance: none; ←selectの矢印消し
appearance: none; ←selectの矢印消し
padding:3px 35px 3px 5px; ←レイアウト保持(ただし労害IE8はきかない)右paddingは、今回のbg用。
background:transparent; ←デフォ背景消し
border:none; ←デフォボーダー消し
border-radius:4px 3px 3px 4px; ←まぁ。
white-space:normal; ←一応折り返して表示してくれるブラウザがある。
position:relative;z-index:-2; ←z-indexのためのrelative。(Web標準外のブラウザIE8用)
■div.input-type-select select(:focus) option{
これは、ただ背景変えてるだけ。
■div.input-type-select select::-ms-expand {
産業廃棄物であるIE10のためにある、selectタグの矢印を消す、ms独自の疑似クラスがあるみたい。
■div.input-type-select:after{
これは、世界の経済的損失の原因になっているIE8のための記述。シングルコロンなのは、イントラを見るためだけのブラウザIE8がダブルコロンをサポートしていないから。
この仕様を逆手に今回は使う。
一つお伝えしておきたいが、IE11などのエミュレーションと、実機のIE8は、挙動がまるで違った。IEtesterのIE8と実機のIE8は、ある程度似ていた。
content:"";display:block;width:10px;height:100%;
position:absolute;right:23px;top:0;z-index:10;
background:#FAF6F5 url("bg.png") no-repeat left center;}
IE8宛にしていることは、矢印部分とテキストの間を、もともとの背景で埋めている。
矢印ごと埋めちゃえばいいだろう、と思うかもしれないが、上位のDOM:afterで埋めると、selectが動作しなくなり、矢印部分がマウスクリックで反応しなくなる。
これは、UI上致命的な欠陥であるため、避けることにした。
ここでも背景画像は、当然dataにしておくといい。
height100%にしているのは、文字拡大対応のため。
↓この部分
くどいかもしれないが、疑似クラスのオブジェクトのz-indexには、IE8特有のバグがある。前述の親要素に対してのシツコイz-index記述は、このため。
■div.input-type-select::after{
これは、歴史の教科書などにのるはずもない、何かの実験台かかませ犬だったのであろうIE9のための記述。(しかし2016年以降もサポートはするようだが。)
ダブルコロンを使い、シングルコロンで使った記述の上書きをする。
区画を作って上書きすることはIE8と同様であるが、その位置は違う。
IE8とIE9での、矢印出現位置が異なることに由来する。
IE9には、inline-blockかつ、selectにpaddingが"効く"ので、この位置に矢印がくる。
transform:は、IE9では実装されていなく、IE10以降に実装されているプロパティ。やってることは、このafterで作った物体を、overflowの外に飛ばし無効化(?)させること。値は適当。これにより、IE9専用の記述ができる。
見た目、矢印部分とテキストにやや開きが生まれるが、
結果的に、それほど違和感がないため、許容した。
ただし、IE8と同様に、押せない部分ができることは免れない。
■*+html
言わずとしれた、ie7。これは、できるだけデフォに戻してるだけ。
まぁ、この流れなら、ie6も対応できますよ、ともいえそう。
結論
ざっとこのソースに対して説明した。
社会的嫌悪の的であるIEの89で少々のバグがあるのがわかると思う。
afterで作った区画は、"押せない"のだ。
また、存在価値がないie8にいたっては、padding分も押せない。
これらのマウスを使った視覚で操作するユーザビリティの担保は、おそらくこの方法のHTML/CSSだけでは賄えない。JSなどで別途機能を作る必要がありそうだ。
また、諸悪の根源であるIE8対策のために、paddingの値をcalcを使うことで操作できる。したがって、widthをフルに使うことなく、本来のinline-block的な挙動に抑えることができる可能性を残している。
さらに別の可能性として、<select>にcolumnを使った手法であれば、もしかしたらIE8に対しての別の解を求めることができるかもしれない可能性をここに残しておく。