divはボタンではない、ボタンの実装について知っておくべきすべてのこと

クリックできるボタンを実装するとき、HTMLの何をよく使用しますか?
buttonタグ、もしくはdivタグ? divを使用してはいけない理由、buttonを使用するときの注意点、場合によってはaがよい理由を紹介します。

ボタンの実装について知っておくべきすべてのこと

Everything you didn’t know you need to know about buttons
by Steve Sewell

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

はじめに

クリックできる要素をHTMLで実装するときにaタグやbuttonタグ、あるいはまったく別のタグ(div?)のどれを使用しますか?

その答えはあなたが思っていたのと少し異なり、中には驚くようなことがあるかもしれません。

ボタンの実装にdivを使用したときの問題点

まずは、1つ明確にすることから始めましょう。クリック可能な要素にdivを使うべきではありません(少なくとも99%のケースで)。
それは、なぜでしょうか?

簡単に説明すると、「divはボタンではない」からです。divは特別な意味を持たないコンテナで、クリック可能な要素が持つべき次の性質が欠けています。
参考: div要素 -HTML Living Standard

  • divは、フォーカス可能な要素ではありません。たとえば、デバイス上の他のボタンのようにtabキーでdivにフォーカスが当たることはありません。
  • スクリーンリーダーなどの支援ツールは、divをクリック可能な要素として認識しません。
  • divはフォーカスされても、spaceバーやreturnキーなどの特定キーによる入力をクリックに変換しません。

ただ、これらの問題はtabindex="0"role="button"といった属性で回避することができます。

そして、ボタンにはフォーカスが当たったというユーザーフィードバックがあるので、ほぼボタンのdivにもフォーカス時のスタイルを設定する必要があります。アクセシビリティに関する懸念事項もすべてクリアする必要があります。

ボタンの重要な動作をすべて手動で実装するということは、大変な作業です。しかし、幸運なことに、(ほとんどの場合)より良い方法があります!

ボタンをbuttonで実装する

buttonタグの優れている点は、デバイス上の他のボタンと同じように動作し、ユーザーや支援ツールが期待するものと全く同じであることです。

フォーカス可能、アクセス可能、キーボード入力可能、フォーカス状態に準拠したスタイルなど、さまざまな機能を備えています!

しかし、buttonには気をつけなければならない問題がいくつかあります。

buttonのスタイルに関する問題点

buttonの実装で一番悩ましいのは、buttonのスタイルです。

たとえば、ボタンの背景を薄紫色にしたいとします。

非常に残念な結果になります。

ボタン

なんだか、古いWindowsのボタンに見えます。
この原因はbutton要素にブラウザは奇妙なスタイルを強制するので、独自のスタイルを適用しても混乱するだけです。

おそらく、これがボタンをdivで実装する理由でしょう。divにはブラウザ独自のスタイルはありません。常に期待どおりに機能し、期待どおりに表示されます。

appearance: none;で外観をリセットすればいいんのでは? と思うかもしれません。しかし、これはあなたが考えているようなことはありません。

appearance: none;を設定しても同じです。

ボタン

buttonのスタイルを正しく設定する方法

buttonをスタイルするには、行ごとにプロパティをリセットする必要があります。

このCSSでdivのように見えて動作するbuttonができます。さらに、ブラウザのデフォルトのフォーカススタイルも使用できるという利点もあります。

もうひとつの方法として、all: unset;を使用して、特別なスタイル設定をしないようにすることもできます。

フォーカス時のスタイルを追加することを忘れないでください。たとえば、十分なコントラストを備えたブランドカラーでアウトラインを設定します。

フォーム内のbuttonの動作を修正する

buttonタグを使用する際には、もう一つ注意しなければならないことがあります。form内にあるbuttonは、デフォルトで送信ボタンとして扱われるため、クリックされるとフォームが送信されます。え、何?

そうなんです、buttonのデフォルトのtype属性がsubmitだからです。これは奇妙で、イライラします。

これを解決するには、ボタンが実際にフォームを送信するものでない限り、常にtype="button"を追加する必要があります。

これで、ボタンが最も近いformの親を見つけて送信しようとすることがなくなりました。ふぅ、面倒ですね。

他のページへのリンクに使用する場合はaタグで

ここで、このルールの大きな例外を一つ紹介します。
他のページへのリンクには、buttonを使用したくありません。

buttonにクリックイベントを使用してページにリンクするボタンを実装した場合、問題点がいくつかあります。

  • buttonはクロール可能ではないため、SEO的に非常に不利です。
  • ユーザーはbuttonで実装されたリンクを新しいタブやウインドウで開くことができません。たとえば、右クリックで「新しいタブで開く」など。

そのため、ナビゲーションにbuttonを使用するのはやめましょう。

そこで頼りになるのが、aタグです。

aタグを使用するもっとも重要な点は、フォーカス可能、アクセス可能、キーボード入力可能であるといった前述のbuttonの利点をすべて備えていることです。そして、ファンキーなスタイルは必要ありません!

ここで「ん?待てよ」と思うかも知れません。abuttonの利点を持ちながら、ファンキーなスタイルの必要がないなら、すべてaで実装すればいいのでは?

しかし、その答えはダメです。hrefを持たないaタグはボタンのように動作しないからです。そうです、ahrefに値があるときだけ、フォーカス可能などのボタンの動作が可能になります。

したがって、ボタンにはbuttonを、リンクにはaを使用するようにしましょう。

ボタンの実装をコンポーネントにする

私が非常に気に入っているパターンの一つは、これらのルールをコンポーネントでカプセル化することです。つまり、MyButtonコンポーネントを用意し、URLを指定すればリンクになり、そうでなければボタンになります。

こうすることで、ボタンの目的がクリックハンドラであろうと、他のページへのリンクであろうと、デベロッパーとユーザーの両方のエクスペリエンスに一貫性を持たせることができます。

そして締めくくりとして、いくつかのタイプも追加してみましょう。

終わりに

ここまで、たくさんありましたね。
要するに、リンクにはhrefプロパティを持つaタグを使用し、他のすべてのボタンにはtype="button"を持つbuttonタグを使用するということです。

sponsors

top of page

©2024 coliss