HTMLでボタンを作るとき使うべき要素は <input>?<button>?
🌼 はじめに
フロントエンドエンジニアなら誰でも一回はボタンコンポーネントを作ったこと、もしくは使ったことがあるのではないかと思います。私もUI実装のときよく触ってました。
最近 <input type="button" value="保存" />
のようなボタンコンポーネントを見かけて、「なんで button
じゃないんだろう、てかなんでボタン作る要素が button
と input
の2つあるわけ?」という気持ちになりました。
気になったら調べるしかないので、今から調査結果を共有します。
input
要素とbutton
要素は似てる
1. さっそくフォームの中にinput
要素とbutton
要素でボタンを作ってみました。
<form action="">
<label>
好きな食べ物は?
<input type="text" />
</label><br />
<div class="buttonArea">
<div class="buttonAreaTitle">input タグのボタン</div>
<input type="submit" value='type="submit"' /><br />
<input type="button" value='type="button"' /><br />
<input type="reset" value='type="reset"' /><br />
</div>
<div class="buttonArea">
<div class="buttonAreaTitle">button タグのボタン</div>
<button type="submit">type="submit"</button><br />
<button type="button">type="button"</button><br />
<button type="reset">type="reset"</button><br />
</div>
</form>
ボタン自体はCSS何も書いてないのでデフォルトデザインが表示されてます。input
要素と button
要素の見た目が同じですね。
実は各type
ごとの機能も同じです。テキスト入力欄に何か入力してからボタンを押してみるとその違いが観察できるので試してみてください。
-
type="submit"
- ボタンを押したらフォームが送信される
- フォームがリロードされ、テキスト入力欄も初期化される
-
type="button"
- ボタンを押したら何も起きない
- フォームも送信されず、入力した値も残ってる -
type="reset"
- ボタンを押したらフォームが初期化される
- フォームは送信されない(リロードされない)
- 入力欄を空欄にするのではなく、初期値に戻す(初期値がない場合空欄に戻す)
type
ごとにこんな違いがあるとも知りませんでした。なるほど、これでボタンの目的に合うtype
を選べるようになりました。
それはいいですが、「見た目も機能も同じなら結局何が違うんだ?」という気持ちもあります。それもまた調べてきました。
2. 終了タグの有無が違う
1番の違いは終了タグの有無です。input
要素は終了要素を持たないのでラベル文字列を value 属性で渡す反面、button
要素は開始タグと終了タグの間にラベル文字列を入れるというところです。
それがなにか?と思うかもしれませんが、終了タグがあるということはタグの内容にimg
など画像データを入れ子にすることもできるし、疑似要素も作れるのでもっと柔軟なスタイリングができます。
試しにinput
要素とbutton
要素両方使って同じデザインのボタンを作ってみました。アイコンの幅は無視してテキストがボタンの真ん中に来る、アイコンはテキストの左隣という要件を想定してます(サイドバー開いたらコードも見れます)
button
要素の場合、テキストを真ん中にするためにテキストにアイコンの幅分のmargin-right
を与えました(ベスプラかはわかりませんw)。これで文言が長くなっても短くなってもUIは崩れないのでよしとします!
input
要素の場合はボタン内のアイコンをposition: absolute;
で浮かせ、left
プロパティを固定値で指定することで位置を調整してます。今は一旦これでそれっぽくなりましが、ボタンラベルの文言が変わったらアイコン位置も一緒に調整しないといけなく、メンテコストが高くなります。また、固定値だとブラウザや端末によって表示が変わるかもしれないという不安が常に心の中に潜むことになるでしょう。ラベルテキストにスタイルを当てられないことが不便ですね。
input
要素でも CSS を頑張ればスタイリングはできるけど button
要素のほうがもっと柔軟にスタイリングできる、という感じですね。
button
要素はinput
要素の進化版
3.これで2つの要素の共通点と違いは理解できました。が、まだ「なぜボタン作る要素が2つなのか」という疑問は残ってます。
その答えはMDNにありました。
メモ:
<input>
要素のbutton
型は完全に妥当な HTML ですが、より新しい<button>
要素が、ボタンの作成にはより好まれるようになりました。<button>
のラベル文字列は開始タグと終了タグの間に挿入され、ラベルに画像を含む HTML を含めることができます。
https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/button
なるほど、button
要素のほうがinput
要素より後で追加された要素ということですね。
ちなみにbutton
要素は HTML4 で追加されたようです。「HTML 4.0 Specification」の17-5に明記されてました(もう20年以上前だった)。
ということは、昔はinput
要素でしかボタンを作れなかったけど、もっといい感じにボタンを作るためbutton
要素が追加されたということですね!すっきりしました。
でもbutton
要素を使うときは一つ注意点があります。
button
要素にtype
を指定しない場合、自動的にデフォルト値であるsubmit
のボタンになるということです。
<!-- 両方 type="submit" のボタン -->
<button>ボタン</button>
<button type="submit">ボタン</button>
ということは、フォーム送信目的じゃないボタンを作るときbutton
要素のtype
指定は省略できないということになります。(省略したらフォームを送信しちゃうから)
まあtype
省略しても Javascript でフォーム送信せず望む動きだけさせることもできますが、面倒だしボタンの意味合い的にも合わない気がするのでtype=button
を指定したほうがいいかなと思います。
4. まとめ
-
input
要素のボタンとbutton
要素のボタン両方妥当な HTML です。 -
button
要素のほうがスタイリングが柔軟にできるので特に理由がなければbutton
要素を使いましょう。 -
button
要素デフォルトtype
はsubmit
なので、フォーム送信目的のボタンじゃない場合はtype="button"
を指定しましょう。
🌷 終わり
input
のtype="image"
もフォームを送信するボタンらしいですね(全然知らなかった)
Discussion