弁護士ドットコム株式会社 Creators’ blog

弁護士ドットコムがエンジニア・デザイナーのサービス開発事例やデザイン活動を発信する公式ブログです。

なぜボタンは button 要素で作るべきなのか、div 要素をボタンにすることを通して考える

この記事を読むとわかること

  • なぜボタンを button 要素で作るべきなのか、その理由
  • どーーーーーしてもボタンを別の要素で作らなければいけないとき、何をすればいいか

答え

button 要素を使ったときに得られる標準動作を捨ててまで得られるメリットがないからです。
HTML の標準に従って、適切な要素を用いて開発することが重要です。

そもそも HTML (HyperText Markup Language) は、ドキュメントの構造や意味を印付けして表すためのマークアップ言語です。
ボタンにはボタンであるという印、つまり button 要素を用いるのが理にかなっています。

button 要素の特徴

button 要素は、標準でこれだけのことをやってくれます。
これが Web 画面における「ボタン」の機能であり、button 要素以外でボタンを作るには、これらを自分で実装しなければなりません。

  • ボタンの見た目の提供
    • ボタンにホバーしたときのカーソルの見た目
    • ボタンを押したときの見た目
    • フォーカス時の見た目
  • フォーカス可能
  • Space キー・Enter キーで操作可能
    • これらのキーを操作したときに、自動で click イベントを発火してくれます。つまり、実装者は、 click イベントのハンドラーを設定するだけで、同時にキーボードのサポートも達成できます
  • 支援技術に対して「これはボタンである」と伝える(暗黙の button ロール)

div要素を完璧なボタンに仕立て上げてみる

押すと "button was hit!" というアラートを表示するボタンを、あえて div 要素を使って作ってみます。
この作業を通じて「こんな不毛な作業をするよりも、button 要素を使うほうが簡単だな」と思っていただければ幸いです。

<div>アラートを表示する</div>

ボタンの見た目をつける

  • 普通のボタンは横に並べることができるので、display: inline-block を設定します。
  • ボタンの見た目はいろいろなパターンを考えられますが、ここではシンプルに外枠を囲って背景色をつけます。
  • 普通のボタンはラベルテキストの選択ができないので、user-select: none を設定します。
  • ホバー時・押下時の見た目をつけます。
<div class="button">アラートを表示する</div>
<style>
.button {
  display: inline-block;
  border: solid 1px #000000;
  background-color: #dddddd;
  user-select: none;
  &:hover {
    background-color: #cccccc;
  }
  &:active {
    background-color: #eeeeee;
  }
}
</style>

結果

(まだ動きません)

アラートを表示する

フォーカス可能にする

  • tabindex="0" を付与します。
  • フォーカスした際の見た目を追加します。
<div 
  class="button"
  tabindex="0"
>
  アラートを表示する
</div>
<style>
.button {
  display: inline-block;
  border: solid 1px #000000;
  user-select: none;
  background-color: #dddddd;
  &:hover {
    background-color: #cccccc;
  }
  &:active {
      background-color: #eeeeee;
  }
  &:focus-visible {
      outline: solid 2px #000000;
  }
}
</style>

結果

(まだ動きません)

アラートを表示する

イベントハンドラーの追加

  • クリックイベントだけでなく、keydown イベントを使って、スペースキー・エンターキーの操作も待ち受けなければいけません。
<div
  id="my-button"
  class="button"
  tabindex="0"
>
  アラートを表示する
</div>
<script>
const proc = () => {
  alert("button was hit!")
}
const btn = document.querySelector("#my-button")
btn.addEventListener("click", proc)
btn.addEventListener("keydown", (e) => {
  if (e.key === " " || e.key === "Enter") {
    e.preventDefault()
    proc()
  }
})
</script>
<style>
.button {
  display: inline-block;
  border: solid 1px #000000;
  background-color: #dddddd;
  user-select: none;
  &:hover {
    background-color: #cccccc;
  }
  &:active {
    background-color: #eeeeee;
  }
  &:focus-visible {
    outline: solid 2px #000000;
  }
}
</style>

結果

(動きます)

アラートを表示する

支援技術のサポート

  • role="button" を追加します。
<div
  id="my-button"
  class="button"
  tabindex="0"
  role="button"
>
  アラートを表示する
</div>
<script>
const proc = () => {
  alert("button was hit!")
}
const btn = document.querySelector("#my-button")
btn.addEventListener("click", proc)
btn.addEventListener("keydown", (e) => {
  if (e.key === " " || e.key === "Enter") {
    e.preventDefault()
    proc()
  }
})
</script>
<style>
.button {
  display: inline-block;
  border: solid 1px #000000;
  background-color: #dddddd;
  user-select: none;
  &:hover {
    background-color: #cccccc;
  }
  &:active {
    background-color: #eeeeee;
  }
  &:focus-visible {
    outline: solid 2px #000000;
  }
}
</style>

結果

(動きます)

アラートを表示する

button要素で実装した場合

同様のボタンを button 要素で実装した場合と比較してみましょう。シンプルですね。

<button id="my-button">
  アラートを表示する
</button>
<script>
const proc = () => {
  alert("button was hit!")
}
const btn = document.querySelector("#my-button")
btn.addEventListener("click", proc)
</script>

結果

(動きます)

まとめ

ボタンをあえて div 要素で作成し、それを button 要素による実装と比較しました。

ご覧いただいたように、button 要素を使ったときに得られる標準動作を捨ててまで、他の要素を用いて実装するメリットはありません。

そもそも HTML (HyperText Markup Language) は、ドキュメントの構造や意味を印付けして表すためのマークアップ言語です。
ボタンにはボタンであるという印、つまり button 要素を用いるのが理にかなっています。

これに限らず、HTML の標準に従って、適切な要素を用いて開発しましょう。