ページに移動するボタンの作り方
普通のリンク <a href> を書き、CSS でボタンのように見せます。他のリンクと同じようにページへ移動し、新しいタブで開く、リンクのアドレスをコピーする、マウスを重ねると URL が表示されるといったリンクの機能もすべて残ります。
リンクをボタンに変えるルールは次のとおりです。
display: inline-blockにすると padding で箱が広がり、テキストの行の中にも収まります。text-decoration: noneで下線を消します。colorとbackgroundで青いリンクの色を置き換えます。:focus-visibleでキーボードの利用者にわかりやすいフォーカスリングを表示します。
同じクラスは <button> にも使えるので、フォームの送信ボタンと別ページへのリンクをまったく同じ見た目にしつつ、それぞれ本来の役割を果たせます。
ボタンかリンクか: どの要素を使うか
判断の基準は見た目ではなく、クリックしたときに何が起きるかです。
| クリックすると | 使う要素 | 例 |
|---|---|---|
| 別の URL に移動する | <a href> | 登録、続きを読む、料金を見る、ダウンロード |
| このページの何かを変える | <button type="button"> | メニューを開く、再生、カートに追加、パスワードを表示 |
| フォームを送信する | <button type="submit"> | ログイン、検索、保存 |
「リンク」と読み上げられるリンクと「ボタン」と読み上げられるボタンは、何が起きるかをスクリーンリーダーの利用者に伝えます。キーボードでの動作も違います。Enter はどちらも作動させますが、Space で作動するのはボタンだけです (リンクで Space を押すとページがスクロールします)。button 要素そのものは HTML のボタン のページで解説しています。
リンクの中にボタンを入れてはいけない理由
多くの人が最初に試すのがこの書き方です。
<!-- Invalid: interactive content inside <a> -->
<a href="/signup"><button>Sign up</button></a>
<!-- Invalid the other way round, too -->
<button><a href="/signup">Sign up</a></button>
HTML の仕様ではどちらも禁止されています。<a> と <button> の中には操作できる要素を入れられません。実際には、1 つの操作に Tab の停止位置が 2 つでき、スクリーンリーダーは「リンク、ボタン、Sign up」と読み上げることがあり、クリックでリンク先に移動するかどうかもブラウザによって変わります。要素は 1 つに決めましょう。
onclick と location.href を使わない理由
よくあるもう 1 つの回避策は、JavaScript で URL を設定するボタンです。見た目はリンクと同じです。
(プレビューが別のページに移動してはいけないので、この例では window.open を使っています。普通は location.href = '...' と書きます。) 2 つにマウスを重ね、右クリックしてみてください。URL を表示し、「リンクを新しいタブで開く」や「リンクのアドレスをコピー」を出すのは本物のリンクだけです。ボタンは Ctrl+クリックも中クリックもできず、ブラウザは訪問済みにせず、検索エンジンもリンクとしてたどりません。移動先が URL なら <a href> と書きましょう。
URL を開くフォームのボタン
別のページに移動する <button> が正しい場面が 1 つあります。データを一緒に送るときです。代表的な例は検索ボックスです。フォームの action が URL で、method="get" で入力内容がクエリ文字列に入ります。
Search を押してみてください。実際のページなら、ブラウザは https://duckduckgo.com/?q=html+button+link に移動します。プレビューは移動する代わりにデータを表示します。2 つ目のボタンの formaction は、同じフォームを別の URL に送ります。
無効にしたリンクボタン
リンクに disabled 属性はなく、<a disabled> は何もしません。リンクボタンを無効にするには href を削除し (href のない <a> はリンクではなく、クリックもフォーカスもできません)、aria-disabled="true" を付けて、スタイルとスクリーンリーダーの両方に伝えます。
プレビューで Tab を押すと、フォーカスは 1 つ目のボタンにしか移りません。href を残して pointer-events: none を付けるサイトもありますが、それで防げるのはマウスだけです。リンクには Tab で移動でき、Enter を押すとリンク先に移動してしまいます。
新しいタブとダウンロードのボタン
ボタンの見た目にしたリンクでも、リンクの属性はすべて使えます。
<a class="btn" href="/files/guide.pdf" download>Download the guide</a>
<a class="btn" href="https://github.com/" target="_blank" rel="noopener">GitHub</a>
これも <a> を使う理由の 1 つです。<button> には download も target もありません。target については リンクを別タブで開く のページを参照してください。
よくある間違い
- リンクの中のボタン、ボタンの中のリンク。 無効な HTML で、動作が予測できません。
- 単なるページ移動に
<button onclick="location.href=...">を使う。 新しいタブもリンクのコピーもできず、クロールもされません。 - ページを移動するリンクに
role="button"を付ける。 スクリーンリーダーの利用者にはボタンがあると伝わるのに、ページが変わってしまいます。リンクのままにしましょう。 - 「削除」や「メニューを開く」などの操作に、
href="#"のボタン風リンクを使う。 何も読み込まないなら<button type="button">を使いましょう。 <a disabled>。 リンクにこの属性はありません。hrefを削除しましょう。display: inline-blockを忘れる。 上下の padding が前後の行に重なります。
よくある質問
HTML で別のページにリンクするボタンを作るには?
リンクを使い、ボタンのようにスタイルを付けます: <a href="/signup" class="btn">Sign up</a> に、CSS で padding、背景、角の丸み、text-decoration: none を指定します。見た目はボタンで、動作はリンクです。実際にリンクだからです。
a タグの中に button を入れられますか?
入れられません。HTML の仕様では、<a> の中に <button> などの操作できる内容を入れることは許されていません。ブラウザによって扱いが異なり、キーボードの利用者には 1 つの操作に 2 つの Tab の停止位置ができ、スクリーンリーダーはわかりにくく読み上げます。要素は 1 つにしましょう。
button に href 属性はありますか?
ありません。<button> に href はありません。ブラウザを URL に移動させるには <a href> を使うか、action を持つ <form> にボタンを入れます (ボタンの formaction 属性で上書きできます)。
ボタンで onclick と location.href を使うのはよくないですか?
動きはしますが、読み手はリンクならではの機能をすべて失います。中クリックや Ctrl+クリックで新しいタブを開くこと、リンクのアドレスのコピー、マウスを重ねたときの URL の表示ができず、検索エンジンもリンクとしてたどりません。移動先が URL なら <a> を使いましょう。
ボタンの見た目にしたリンクを無効にするには?
リンクに disabled 属性はありません。href を削除してリンクでなくし、aria-disabled="true" を付けて、無効の見た目にします。再び使えるようにするときは href を戻します。