Ateam Brides Inc. Advent Calendar 2021の10日目はデザイナーの綿貫(@xrxoxcxox)がお送りします!
この記事の概要
ボタンっぽい見た目の要素をクリックしたら検索フォームが動くとか自分のプロフィールを更新するとか、そういうインターフェースはたくさんありますよね。
ときどきdivやspan要素にaddEventListener('click', function)をつけて動かしているのを見かけるのですが、結局改善を求められるはずでしかも工数がかかります。
というわけでシンプルにbuttonを使いましょう、と啓蒙する記事です。
伝えたいこと
ボタンっぽい役割の要素であればbuttonタグを使いましょう!
この1点のみです!
divやspanでボタンっぽい要素を作るとどうなるの?
- タブキーでフォーカスを当てられない
-
enterやspaceでボタンのアクションを実行できない - スクリーンリーダーが適切に読み上げてくれない
というわけで非常に使いづらくなります。
あなたの作っているプロダクトを使ってくれている人から「ボタンが操作できないので修正してもらえませんか?」と意見をいただければラッキーで、上手く使えないからと静かに去ってしまう可能性もあるかもしれません。
特にキーボードのみで操作している人にとってはクリティカルな問題になり得ます。
divやspanでボタンっぽい要素を作った場合、改善する方法
まずは最初の時点のコードを載せます
<div id="div" class="button">ボタン風のdiv</div>
const div = document.getElementById('div');
const divClick = () => {
alert('divがクリックされました');
};
div.addEventListener('click', divClick);
| クリックだけならbuttonとdivの差は無く見える |
|---|
![]() |
tabindexをつける
- <div id="div" class="button">ボタン風のdiv</div>
+ <div id="div" class="button" tabindex="0">ボタン風のdiv</div>
tabindexをつけないと、そもそもタブキーでフォーカスを当てることができません。
タブキーでリズミカルに進んでいたのに、アクションを起こすためのボタンでつんのめってしまいます。
| tabindexが無いのでフォーカスがあたらない | tabindexがあるのでフォーカスがあたる |
|---|---|
![]() |
![]() |
keydownのeventListenerを登録する
keydownがないと、せっかくフォーカスがあたってもキーボードからアクションを起こせません。
enterとspaceを登録して、クリックとは別な処理として書く必要が出てきます。
const div = document.getElementById('div');
const divClick = () => {
alert('divがクリックされました');
};
+ const divKeydown = (e) => {
+ if (e.keyCode === 13 || e.keyCode === 32) {
+ alert('divに対してキーが押されました');
+ }
+ };
div.addEventListener('click', divClick);
+ div.addEventListener('keydown', divKeydown);
| keydownが無いのでenterを押しても反応がない | keydownがあるのでenterを押すと反応する |
|---|---|
![]() |
![]() |
buttonのroleを追加する
- <div id="div" class="button" tabindex="0">ボタン風のdiv</div>
+ <div id="div" class="button" tabindex="0" role="button">ボタン風のdiv</div>
操作するタイミングでは問題がなくなりましたが、まだマークアップとしてはdivでしかないのでスクリーンリーダーが上手く認識してくれません。
しっかりbuttonであると明示する必要があります。
※少し見づらいですが、右下に出してあるVoiceOverに表示されている内容が変わっています。
| roleが無いのでdivと認識されたまま | roleがあるのbuttonと捉えられる |
|---|---|
![]() |
![]() |
上記の内容はbuttonタグなら全く実施しなくてOK
たとえば、何かの処理を作る度にキー押下の判定を加えるのは面倒ですよね?(仮にユーティリティな関数として切り出したとしても、毎回呼び出すこと自体が面倒だと思います)
けどこれらは正しいマークアップ、つまりbuttonタグを使ってさえおけば何も実施しなくてOKなんです。
使わない手はありませんね。
まとめ
- ボタンっぽい要素を
divやspanで作ってしまうと- タブキーでフォーカスを当てられない
-
enterやspaceでボタンのアクションを実行できない - スクリーンリーダーが適切に読み上げてくれない
-
buttonで作れば上記の問題は起きない






