LoginSignup
73
31

More than 1 year has passed since last update.

divやspanでボタンっぽい要素を作ると大変なことになるからbuttonを使おう

Last updated at Posted at 2021-12-22

Ateam Brides Inc. Advent Calendar 2021の10日目はデザイナーの綿貫(@xrxoxcxox)がお送りします!

この記事の概要

ボタンっぽい見た目の要素をクリックしたら検索フォームが動くとか自分のプロフィールを更新するとか、そういうインターフェースはたくさんありますよね。

ときどきdivspan要素にaddEventListener('click', function)をつけて動かしているのを見かけるのですが、結局改善を求められるはずでしかも工数がかかります。

というわけでシンプルにbuttonを使いましょう、と啓蒙する記事です。

伝えたいこと

ボタンっぽい役割の要素であればbuttonタグを使いましょう!

この1点のみです!

divspanでボタンっぽい要素を作るとどうなるの?

  • タブキーでフォーカスを当てられない
  • enterspaceでボタンのアクションを実行できない
  • スクリーンリーダーが適切に読み上げてくれない

というわけで非常に使いづらくなります。
あなたの作っているプロダクトを使ってくれている人から「ボタンが操作できないので修正してもらえませんか?」と意見をいただければラッキーで、上手く使えないからと静かに去ってしまう可能性もあるかもしれません。

特にキーボードのみで操作している人にとってはクリティカルな問題になり得ます。

divspanでボタンっぽい要素を作った場合、改善する方法

まずは最初の時点のコードを載せます

index.html
<div id="div" class="button">ボタン風のdiv</div>
script.js
const div = document.getElementById('div');

const divClick = () => {
  alert('divがクリックされました');
};

div.addEventListener('click', divClick);
クリックだけならbuttonとdivの差は無く見える
default.gif

tabindexをつける

index.html
- <div id="div" class="button">ボタン風のdiv</div>
+ <div id="div" class="button" tabindex="0">ボタン風のdiv</div>

tabindexをつけないと、そもそもタブキーでフォーカスを当てることができません。
タブキーでリズミカルに進んでいたのに、アクションを起こすためのボタンでつんのめってしまいます。

tabindexが無いのでフォーカスがあたらない tabindexがあるのでフォーカスがあたる
focus-before.gif focus-after.gif

keydownのeventListenerを登録する

keydownがないと、せっかくフォーカスがあたってもキーボードからアクションを起こせません。
enterspaceを登録して、クリックとは別な処理として書く必要が出てきます。

script.js
  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を押すと反応する
keydown-before.gif keydown-after.gif

buttonのroleを追加する

index.html
- <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と捉えられる
role-before.gif role-after.gif

上記の内容はbuttonタグなら全く実施しなくてOK

たとえば、何かの処理を作る度にキー押下の判定を加えるのは面倒ですよね?(仮にユーティリティな関数として切り出したとしても、毎回呼び出すこと自体が面倒だと思います)

けどこれらは正しいマークアップ、つまりbuttonタグを使ってさえおけば何も実施しなくてOKなんです。

使わない手はありませんね。

まとめ

  • ボタンっぽい要素をdivspanで作ってしまうと
    • タブキーでフォーカスを当てられない
    • enterspaceでボタンのアクションを実行できない
    • スクリーンリーダーが適切に読み上げてくれない
  • buttonで作れば上記の問題は起きない
73
31
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
73
31