Gazelle
2021年01月23日公開 2572 Views

【CSS】ラジオボタンのレイアウトにはlabelと隣接セレクタを使うべし

inputに対してCSSで変更を加えて、ボタンの大きさや形を変えようとしてまず思いつく方法が、labelでinputタグを囲い、囲ったタグに対してスタイルを当てるというものだろう。例えば下記のような感じ

<label id="desktop">
  <input type="radio" name="kind" value="1">デスクトップ
</label>
<label id="note" class="selected">
  <input type="radio" name="kind" value="2" checked>ノート
</label>

inputにdisplay:noneを設定して、labelにcssを当てて任意のボタンをデザインする。

しかしこのやり方ではラジオボタンを切り替えた時に親のlabelのselectedクラスを変えるのが非常に面倒であり、inputが押される => バブリングで親クラスをハンドルする => 親属性にselected属性を付与するといったことをJavaScriptで操作を行わなければならない。
今回はこの問題をCSSのみで解決したい

これには

  • inputとlabelを並列におく
  • inputからの隣接セレクタを用いてlabelにレイアウトを当てる

ということをしてやれば良い。こんな感じ

See the Pen Radio Button by tomson (@ks4162yt) on CodePen.

簡単に解説すると、labelのforプロパティにinputのid属性を指定することによりinputボタンをlabel側にも拡張できる。すなわち、labelをクリックしたときもinputがクリックされたと見なされる

次にdefaultのinputが表示されないようにinputにdisplay:noneを設定する。またlabelにもレイアウトを施す。

最後に隣接セレクタ+を使用して、inputにcheckが入った時にlabelのレイアウトを変更する

labelがクリックされたとしてもラベルに何か属性情報が付与されるわけではなく、input側にcheck属性が付与されるだけである。このため隣接セレクタを使いinputの変更をlabel側に反映させてやるのである。ここが今回の肝となる。

値の取り出しはjqueryを使えば簡単で

$('[name=kind]').val();

でとラジオボタンのname属性を指定して簡単に取り出せる。JQueryを使わない場合は

Array.apply(null, document.getElementsByName('kind')).filter(elem => elem.checked)[0].value;

で取得できる。少しややこしいがjavascriptでradioボタンの値を1行で取得する方法にて解説している。

ホームへ戻る