なぜ「aタグ以外」のクリックイベントは、現場で地雷になりやすいのか
フロントエンドの現場で、「とりあえず`span`に`onclick`付けておけば動くでしょ」というコードを見かけることがあります。プロトタイプならまだしも、そのまま本番環境にデプロイされているのを見ると、正直背筋が凍ります。
なぜなら、HTMLのインライン要素にクリックイベントを付与するという行為は、Webのアクセシビリティという観点において、本来「やってはいけないこと」の筆頭格だからです。
今日は、なぜ`a`タグ以外のインライン要素(`span`, `div`など)にクリックイベントを付けるのが危険なのか、そしてどう実装すれば「プロの仕事」と言えるのか、その裏側と解決策を深掘りします。
—
ブラウザが裏側で行っている「当たり前」の処理
まず、仕様の話をしましょう。ブラウザは、`a`タグや`button`タグに対しては、OSネイティブのイベントとして「EnterキーやSpaceキーによるアクティベーション」を自動的に付与しています。
一方で、`span`や`div`といった要素は「単なるテキストやレイアウトの箱」であり、ユーザーとのインタラクションを想定していません。そのため、これらにJavaScriptで`click`イベントを付与しても、キーボード操作は一切無視されます。
結果として何が起きるか。視覚障害者や、キーボードのみで操作を行うパワーユーザー、あるいはマウスが故障したユーザーは、あなたの作ったボタンを一切「押すことができない」のです。これはフロントエンドエンジニアとして、あってはならない「機能の欠落」です。
—
実践:妥協なき「カスタムクリック要素」の作り方
もし、どうしても`a`タグや`button`タグを使えない(あるいは使いたくない)UIデザインを実装しなければならない場合、最低限以下の3点を満たす必要があります。
1. `tabindex=”0″` を付与してフォーカス可能にする
2. `role=”button”` を付与してスクリーンリーダーに役割を伝える
3. `keydown` イベントで「Enter」と「Space」を拾う
これらを実装した、現場で即戦力となるコードがこちらです。
/
- インライン要素を擬似ボタン化するためのアクセシビリティ対応
- @param {HTMLElement} element – クリック対象の要素
- @param {Function} callback – クリック時に実行する処理
/
function setupAccessibleClick(element, callback) {
// 1. キーボードでフォーカスできるようにする
element.setAttribute(‘tabindex’, ‘0’);
// 2. スクリーンリーダーに「これはボタンである」と伝える
element.setAttribute(‘role’, ‘button’);
// マウス/タッチ操作用
element.addEventListener(‘click’, callback);
// 3. キーボード操作対応
element.addEventListener(‘keydown’, (event) => {
// Enter または Space キーが押されたときのみ実行
if (event.key === ‘Enter’ || event.key === ‘ ‘) {
// Spaceキーのデフォルト動作(画面スクロール)を抑制
event.preventDefault();
callback();
}
});
}
// 使用例
const myCustomButton = document.querySelector(‘.js-my-button’);
setupAccessibleClick(myCustomButton, () => {
console.log(‘ボタンが押されました!’);
});
—
なぜ「Spaceキー」までハンドリングするのか?
コードを見て「Spaceキーまで必要?」と感じた方もいるかもしれません。しかし、これはWebアクセシビリティの標準的な作法です。
ブラウザのネイティブな`button`要素を触ってみてください。Spaceキーを押すと、フォーカスが当たった状態でボタンが押下されます。この「ブラウザ標準の挙動」を再現することこそが、ユーザーにとっての「直感的な体験」を守ることに繋がります。
また、`event.preventDefault()`を忘れると、Spaceキーを押した瞬間に画面がガクッと下にスクロールしてしまいます。これもまた、ユーザーをイライラさせる大きな原因です。
—
最後に:エンジニアとしての矜持
ここまで解説してきましたが、正直に言えば、「基本的には`button`タグを使ってください」というのが私の結論です。
`button`タグを使えば、今回実装した`tabindex`も`role`も`keydown`ハンドリングも、すべてブラウザが勝手にやってくれます。車輪の再発明をする必要はありません。それでもなお、`span`や`i`タグにクリックイベントを付けるという選択をするなら、それは「標準的な挙動をすべて自分で制御する」という責任を背負うことと同義です。
フロントエンド開発は、ただ画面を動かすだけの仕事ではありません。「誰が、どんな環境で使っても、等しく機能にアクセスできること」。これこそが、私たちが守るべき最後の砦です。
皆さんのプロジェクトでも、今日のコードを参考に、もう一度「そのボタン、キーボードでも押せる?」と自問自答してみてください。それが、一段上のエンジニアへと成長する近道です。

コメント