フォーム・入力

ボタン

解説あり

Button

すべての基本。button 要素を使えば得られるアクセシビリティと、自作の落とし穴。

ボタンとは?

ボタンは、押すと「その場で何かが起きる」操作のための部品です。 送信・いいね・モーダルを開く・再生/停止など、ページ内のアクションを実行するときに使います。

Web には最初から <button> という専用要素があり、これを使うだけで、押せること・キーボード操作・支援技術への通知が自動的に揃います。

なぜアクセシビリティが大事なの?

「クリックできる <div>」は、マウス利用者には動いて見えますが、次の人たちには壊れています。

<button> なら、これらすべてが最初から解決されています。

ライブデモ(推奨実装)

下の2つのボタンは APG に沿った実装です。マウスを使わずTab で移動し EnterSpace の両方で押してみてください。

ネイティブ button

試してみよう:Tab でフォーカス → Enter でも Space でも数が増える。disabled のボタンはフォーカスも反応もしない。

ポイント

スクリーンリーダーでフォーカスすると「いいね, ボタン」、無効なほうは 「送信済み, 淡色表示, ボタン」のように役割と状態が読み上げられます。 これらは <button>disabled 属性だけで自動的に得られます。

キーボード操作

キー動作必須/任意
Tab次 / 前のボタンへフォーカス移動(無効なボタンは飛ばされる)必須
Enterフォーカス中のボタンを押す必須
Spaceフォーカス中のボタンを押す必須

補足

<button> なら、この表のすべてがコードを書かずに動きます。リンク(<a>)は Enter のみ、ボタンは EnterSpace の両方で 活性化するのが正しい挙動です。

必要な WAI-ARIA / ロール

付ける場所属性 / ロール意味
ボタン(推奨)<button type="button">ロール・フォーカス・キー操作がすべて自動。ARIA は基本不要
フォーム送信type="submit" / type="button"意図しない送信を避けるため、送信でないボタンには type="button" を付ける。
無効化disabled操作不可にし、フォーカスからも外す。支援技術にも伝わる。
div で代用する場合のみrole="button" + tabindex="0"「ボタン」と認識させ、フォーカス可能にする。さらにキー処理の自作が必須

実装:推奨パターン(Good)

良い例 / 推奨

迷ったら <button>click を1つ書くだけで全入力手段に対応します。

マークアップ:

<!-- これだけで「ボタン」として完璧に動く -->
<button type="button" id="like-btn">
  いいね(<span id="like-count">0</span>)
</button>

スクリプト(click だけでマウス・Enter・Space をカバー):

const btn = document.getElementById('like-btn');
const count = document.getElementById('like-count');

if (btn && count) {
  // click だけ書けば、マウス・Enter・Space すべてで発火する
  btn.addEventListener('click', () => {
    count.textContent = String(Number(count.textContent) + 1);
  });
}

補足

どうしても <div> で作らざるを得ないときは、最低でもrole="button"tabindex="0"Enter/Space のキー処理が必要です。<button> 1つで済むものが、これだけ増えます。

<!-- どうしても div で作る場合(非推奨)に最低限必要なもの -->
<div role="button"
     tabindex="0"
     id="like-div">
  いいね
</div>
const el = document.getElementById('like-div');

if (el) {
  el.addEventListener('click', activate);
  // button なら不要な「キー処理」を自前で書く必要がある
  el.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault(); // Space のスクロールを止める
      activate();
    }
  });
}
function activate() { /* ... */ }

アンチパターン(Bad)

下は <div>onclick を付けただけの「ボタン風」です。マウスでは押せますが、キーボードでは触れず、Space でも反応しません。上のデモと比べてみてください。

div で作った壊れたボタン
いいね(0

試してみよう:Tab で到達できず、Space でも反応しません。スクリーンリーダーでは「ボタン」と読み上げられず、無効状態も表現できません。

<!-- ❌ アンチパターン:div を onclick で「ボタン風」にしただけ -->
<div class="btn" onclick="like()">いいね</div>

悪い例 / 避ける

この実装の問題点:

  • キーボードでフォーカスできないdivTab の対象外。
  • Space / Enter で動かない — キー処理を自作していない。
  • 役割が伝わらない — スクリーンリーダーに「ボタン」と認識されない。
  • 無効化できないdisabled の概念がなく、押せない状態を伝えられない。

ポイント

「リンクっぽい見た目だけどページ移動しない」ものや、「ボタンっぽいけど別ページへ飛ぶ」ものは混乱のもとです。その場で何かを実行するなら <button>、別の場所へ移動するなら <a href> と 役割で選びましょう。

実装チェックリスト


原文(英語):Button Pattern — W3C APG(新しいタブで開きます)