自分自身かその子孫要素にフォーカスがある場合にスタイルを設定できる、CSS擬似クラスの:focus-withinを使ってみます。
対応ブラウザ
対応ブラウザはIEで非対応ですが、それ以外の主要なブラウザではサポートされているようです。
サンプルコード
例として、色々なフォーム部品の入ったフォームを用意します。
<form>
<div class="form-item">
<label for="name">名前</label>
<input type="text" id="name" name="name">
</div>
<div class="form-item">
<label for="area">エリア</label>
<select id="area" name="area">
<option>東京</option>
<option>大阪</option>
</select>
</div>
<div class="form-item">
連絡
<label for="tel"><input type="checkbox" name="contact[]" value="電話" id="tel"> 電話</label>
<label for="mail"><input type="checkbox" name="contact[]" value="メール" id="mail"> メール</label>
</div>
<div class="form-item">
時間帯
<label for="hour-1"><input type="radio" name="hour" value="8:00〜12:00" id="hour-1"> 8:00〜12:00</label>
<label for="hour-2"><input type="radio" name="hour" value="12:00〜16:00" id="hour-2"> 12:00〜16:00</label>
<label for="hour-3"><input type="radio" name="hour" value="16:00〜20:00" id="hour-3"> 16:00〜20:00</label>
<label for="hour-4"><input type="radio" name="hour" value="20:00〜24:00" id="hour-4"> 20:00〜24:00</label>
</div>
<div class="form-item">
<label for="content">内容</label>
<textarea id="content" name="content"></textarea>
</div>
<div class="form-item">
<a href="">リンク</a>
</div>
<div class="form-item">
<button>ボタン</button>
</div>
</form>
フォーム部品の祖先要素にある .form-item に対して、 :focus-within で背景色がつくように設定します。
.form-item {
transition: 500ms;
}
.form-item:focus-within {
background: skyblue;
}
これで各フォーム部品やリンクにフォーカスが当たった際に、背景色がつくようになりました。
:focus-withinのデモページ
上記デモで試してみたところ、挙動で気になる点が2つありました。
1つ目はSafariでチェックボックスやラジオボタンをクリックした際、:focus-withinが効かない点です。
キーボード操作でフォーカスを移動した場合は効いているのですが、クリックの場合はフォーカスと認識されてない?ようでした。
補足で以前に記事を投稿しましたが、チェックボックスやラジオボタンへのキーボードでのフォーカス移動は、デフォルトだと Option + tabキーになります。
2つ目はchrome・Firefox・Edgeで、チェックボックスやラジオボタンをクリックしてフォーカスを切り替えた際、クリック箇所がテキストだと一瞬:focus-withinが外れてしまう(背景がチラつく)という点です。
これはクリック時にマウスボタンを押して離さないとクリックと認識されない(フォーカスが移動しない)ので、マウスボタンを押された段階で現状のフォーカスが外れるのに対して、クリック中の要素にはフォーカスがまだ当たっていないという状態が発生してしまうため起きるようで、キーボード操作で切り替えた場合は発生しないようでした。
2つ目の対策としては、フォーカスが外れた際に少しだけdelayを設定すると多少改善されるかもしれません。
.form-item {
transition: 500ms;
transition-delay: 100ms;
}
.form-item:focus-within {
transition-delay: 0ms;
background: skyblue;
}
これで通常のクリックであればチラつくことがなくなりましたが、クリック中に少し長押しになったりするとその間だけフォーカスが外れることになるので、チラつきの問題は発生します。
delayの設定追加のデモページ
コメントが承認されるまで時間がかかります。