適当おじさんの適当ブログ

技術のことやゲーム開発のことやゲームのことなど自由に雑多に書き連ねます

ラジオボタンをCSSで異なる見た目にしてみたメモ

はじめに

ラジオボタン、つまり、<input type="radio"> のクリック領域を広げて、かつ、見た目を変えてみたいと思ってCSSで色々いじくってみたときのメモです。とりあえず、<input type="radio"> を並べただけの以下のようなラジオボタンをカスタマイズしていきます。

f:id:subarunari:20180413221628p:plain:w400

<input type="radio" name="default" value="one" checked> 選択肢その1
<input type="radio" name="default" value="two"> 選択肢その2
<input type="radio" name="default" value="three"> 選択肢その3

CSSだけでこんな感じの旧来のラジオボタンとは違った見た目を目指します。

f:id:subarunari:20180415175138p:plain:w400

文字列の部分をクリック可能にする

ラジオボタンのクリック対象は丸の部分だけです。丸の部分までマウスカーソルを持って行かずに雑に項目をクリックできるようにします。「ラジオボタンの文字の部分」をクリックできるようにするという方法がよく取られます。

1. labelタグのfor属性を使う

inputのid属性とlabelのfor属性に同じ名前を指定することで、ラベルをクリックして選択可能になります。この方法も次の方法も見た目はまったく変わりません。ラベル部分がクリック可能になるだけです。

<input type="radio" id="label1" name="labeled" value="one" checked><label for="label1"> 選択肢その1</label>
<input type="radio" id="label2" name="labeled" value="two"><label for="label2"> 選択肢その2</label>
<input type="radio" id="label3" name="labeled" value="three"><label for="label3"> 選択肢その3</label>

2. labelタグで囲う

inputタグをlabelタグで囲むことで、同様にラベルで選択可能になります。

<label>
    <input type="radio" name="labeled" value="one" checked> 選択肢その1
</label>
<label>
    <input type="radio" name="labeled" value="two"> 選択肢その2
</label>
<label>
    <input type="radio" name="labeled" value="three"> 選択肢その3
</label>

補足: ラジオボタンを縦に並べる

横に並んでいると文字とラジオボタンの対応がわかりづらいです。縦に並んでいれば、ラジオボタンとラベルの対応は一目瞭然です。また、横幅や文字の折り返しをあまり気にしなくて良くなるので、ローカライズもしやすくなります。

f:id:subarunari:20180413214921p:plain:w300

ということで、この記事の本題ではありませんがラジオボタンを縦に並べてみます。「labelタグで囲う」の方法であればラジオボタンと文字が一括りになるので、.radio-vertical のように指定するだけで、ラジオボタンと関連する文字を縦に並べられます。

<div class="radio-vertical">
    <label>
        <input type="radio" name="labeled" value="one" checked> 選択肢その1
    </label>
    <label>
        <input type="radio" name="labeled" value="two"> 選択肢その2
    </label>
    <label>
        <input type="radio" name="labeled" value="three"> 選択肢その3
    </label> 
</div>
.radio-vertical {                                          
    flex-direction: column;                                                       
    display: inline-flex;                                                         
}  

見た目をカスタマイズする

「ラベルをクリックして選択できるとなると、radioはなくてもよいのではないか?」と考えるようになりました。試しに、<input type="radio">display: none にしてみます。

f:id:subarunari:20180415210130g:plain:w400

白くて丸いラジオボタンはなくなりましたが、ラジオボタンとまったく同じ働きをします。しかし、radioを非表示にしたことで「現在の選択状況」と「選択可能な項目か」という2つの重要な目印が失われてしまいました。このままでは少し不親切です。そこで、labelでこれらを表現するようなCSSを書きます。

input[type="radio"]:checked で見た目を切り替える

CSSのセレクタを input[type="radio"]:checked とすることで、「ラジオボタンが選択されているときのみ」という条件付きのスタイルを作成できます。このセレクタを上手く使うと、ラジオボタンのような振る舞いを他の要素にさせることができます。つまり、「現在の選択状況」と「選択可能な項目か」を他の要素で表現できます。

セレクタで指定しやすいように、HTMLは「1. labelタグのfor属性を使う」のパターンにしています。

<div class="custom-radio">
    <input type="radio" id="custom1" name="custom" value="one" checked><label for="custom1">選択肢その1</label>
    <input type="radio" id="custom2" name="custom" value="two"><label for="custom2">選択肢その2</label>
    <input type="radio" id="custom3" name="custom" value="three"><label for="custom3">選択肢その3</label>
</div>
.custom-radio label {
    color: #ddd;
}
.custom-radio label:hover
{
    color: #888;
}
.custom-radio input[type="radio"]:checked + label {
    color: #000;
    border: 1px solid #000;
}

labelタグのデフォルトの色をグレーにしておき、チェックされたときに黒にすることで、「現在の選択状況」と「選択可能な項目か」を表現しています。また、ホバー時に色を少し変化させることで操作できそうな印象を与えています。他の<input type="radio">に影響を与えないように、<div class="custom-radio">で要素全体を囲っています。

f:id:subarunari:20180415205807g:plain:w400

これについては横並びのままとしています。ラジオボタンがないので、横並びにしてもユーザを困惑させることがないためです。

OS選択UIを作ってみる

上記を踏まえて、OS選択UIを作ってみました。

f:id:subarunari:20180415172824g:plain:w400

枠線内であればどこをクリックしても選択できます。選択された要素は色が変化するので「現在の選択状況」も表現できています。先ほどの例と同様に、ホバー時に少し色を濃くすることで操作できそうな感じを出し、カーソルもデフォルトのポインタから指のやつに変更しています。

HTMLとCSSは下記のような感じです。ちなみに、OSのアイコンには Font Awesome を使っています。

<div class="select-os">
    <input type="radio" id="windows" name="os" value="windows" class="windows" checked>
    <label for="windows">
        <i class="fab fa-windows"></i> Windows
    </label>
    <input type="radio" id="osx" name="os" value="osx" class="osx">
    <label for="osx">
        <i class="fab fa-apple"></i> OSX
    </label>
    <input type="radio" id="linux" name="os" value="unix" class="linux">
    <label for="linux">
        <i class="fab fa-linux"></i> Linux
    </label>
</div>
.select-os input {
  display: none;
}
.select-os input[type="radio"]:checked.windows + label {
  color: #3275bc;
  border: 2px solid #3275bc;
  background-color: #d0e6fd;
}
.select-os input[type="radio"]:checked.osx + label {
  color: #000;
  border: 2px solid #000;
  background-color: #eaeaea;
}
.select-os input[type="radio"]:checked.linux + label {
  color: #bf9701;
  border: 2px solid #bf9701;
  background-color: #fbf4dc;
}
.select-os label {
  color: #ddd;
  border: 2px solid #ddd;
  text-align: center;
  display: inline-block;
  padding: 5px 0px;
  width: 120px;
}
.select-os label:hover {
    color: #aaa;
    border: 2px solid #aaa;
    cursor: pointer;
}

おわりに

以上、ラジオボタンをCSSで異なる見た目にしてみたメモでした。display:noneでラジオボタンを消して input[type="radio"]セレクタを使うことで、labelにラジオボタンと同じような振る舞いをさせました。

旧来のラジオボタンのままであれば、これまでの経験からユーザは操作方法を理解しています。しかし、今回のような異なる見た目にしてしまった場合、ユーザはパッと見で操作できるかどうかわかりません。見た目を変える場合は、ホバーエフェクトを入れたり、「以下の項目から選択してください」といったテキストをすぐ上に配置するなど、操作を促す工夫が必要です。