SELECT要素のテキストを中央揃えにする

Webkit で表示するウェブアプリ製作の過程で SELECT (正確には OPTION になるかな)の要素内に表示されるテキストを中央揃えにする必要があって調べてみたところ面白いやり方が Stack Overflow にあったので紹介します。

もちろん最初に思いつくのは、スタイルシートを使って text-align: -webkit-center; とすることなのだけど、iOS では使えないことがそもそも知られている上に、開発環境の検証に使っている OS X の Safari 8 でも廃止されているようで上手く表現できずに却下することにしました。

次に考えたのは OPTION 要素のテキスト幅に合わせて SELECT 要素の幅を JavaScript から CSS で制御するという方法で、これと同じ発想を持った人がいたということです。

具体的には、まず SELECT の CSS を display: block; としておきつつ、width: 0 auto; を使って、あらかじめ用意しておいた固定幅を持つ親要素内で中央に配置するようにします。

それから、適当な要素(SPAN が適任!)をどこにでもいいので用意(詳細は後述)し、SELECT の ONCHANGE イベントで、選択された OPTION の TEXT 値を取得し、その要素に一時的に入れます。

ここまでくると結果は容易に想像できると思うのですが、その幅を読み取り、SELECT に適応するという手筈になります。

参考にしたコメントでは jQuery を使っていたのですが、今回のプロジェクトでは利用していなかったため次のような関数を使って SELECT の ONCHANGE イベントで呼ばれる関数内で発動することにしました。

var setSelectWidth = function(elm) {
  if(elm.selectedIndex < 0) {
    return;
  }
  var elm_tmp = document.getElementById('width_tmp');
  elm_tmp.innerHTML = elm.options[elm.selectedIndex].text;
  elm.style.width = elm_tmp.offsetWidth + 'px';
};

先に「後述」と書いたのは、この一時的にテキストを入れて幅を読み取る SPAN 要素の扱いで、これまた参考したものでは display: none; としつつも、jQuery の width() で幅を取得できているのですが、offsetWidth を使った場合は上手くいかず、代わりに position: absolute; として画面領域外にぶっ飛ばしておくという alert のタイトルを省いた時のような小技を使いました。

更に参考文では、SELECT に適用する幅の値に余白を与えていますが、SELECT に PADDING: 0; の設定と、両方の要素のフォントを揃えておくことで不要になるかと思います。また、 -webkit-appearance の設定の仕方で結果が若干変わってくることも考えられるので、SELECT の CSS に BORDER を付けて逐一確認するのが良いかと思います。

最後に疑問点としては、offsetWidth ではなくて clientWidth を使うとどうなるのか、ということと、display: none; の指定がある要素の幅を jQuery の width() はどのように取得しているのか、ということで、毎度ながら時間が許せば調べてみたいところです。

P.S. 右揃えだけなら dir 属性を使うと簡単に解決します。

参照:

投稿者: hkitago

個人事業主の iOS, Android, ウェブアプリ開発者で一児の父親。JavaScript, ActionScript, AppleScript, PHP, SQL, ObjC, Swift, Java の読書実行試験運用管理を生業とし、Bind, Postfix, Apache を MacOS で使い、エディタは Vim, mi, Kod, Smultron, TextWrangler を経て Xcode, Android Studio といった IDE と CotEditor (最近TextMate) を重用しています。