ブラウザデフォルトの select
要素は、いろいろな事情で JavaScript でゼロから実装しないといけない場合はあるにせよ、特に理由がなければそのまま使うことが望ましい。独自に実装したものはどうしても、デフォルトのものよりユーザビリティーやアクセシビリティーの面で劣ってしまう。
とはいえそのまんま使うとデザインにそぐわない場面は少なくないし、デザイナーがゆるさんという場合だってある。見た目を変更しなきゃいけない時はよくある。
UA が提供する見た目があまりにもデザインとマッチしなければ select
の見た目を CSS を使って調整することになる。このやり方は最近では一般的になってきていて、Google などでも使われている(路線検索時)など。やり方をググればブログなどがいくつか引っかかる程度にはメジャーだ。が、これらは全部、幅を固定しなければいけないという制約がある。
そういうわけで、幅を可変にしつつ、select
の見た目を独自にデザインする方法を探った。
成果物はこちら。
特徴
- 幅を固定する必要がない
- テキストと並べて置ける
- キーボードフォーカスが当てられる
- キーボードの上下で移動ができる
- 候補の最初の文字をタイプすることで頭出しができる
max-width
を設定できる
ちょっと解説
可変幅はどうやって実現しているかというと、まず <select>
には width
を指定していない。値を反映する .select-value
には position: absolute
しつつ上下左右(top
, right
, bottom
, left
)を 0 とすることで <select>
と同じ大きさになるよう制御している。
.select-select
の padding-right
などがマジックナンバー的になっているのがちょっと心残り。この値は本来、 <select>
がもともと持っている下向き矢印の箱の大きさを加味せねばならず、この箱の大きさは OS や UA、画面の解像度などで変わってくるため完璧に安全な数値が出せないっぽい。appearance: none;
も試したけれど、 Firefox で下向き矢印が消えないのでダメだった。
JavaScript がやっていることは、選択内容を変更を監視して表示に反映しているだけになっている。JavaScript の介入を極力控えめにすることでユーザビリティ、アクセシビリティが損なわれるのを防いでいる。そのためキーボードフォーカス、キーによる上下移動、候補の頭出しなどができる。
change
イベント以外に keydown
イベントも監視している。これは Firefox でキーの上下操作をしても change
イベントが発火されないという仕様による。Firefox が悪いというわけではないみたい。keyup
イベントでもよかったのだけど、画面への反映が遅れるのがいやだったので、keydown
イベントを監視しつつ、setTimeout
を使って一瞬遅らせることで表示の反映をした。
対応ブラウザ
- IE 8以上
- その他の今どきのブラウザ