button
要素で画像ボタンを作る
フォームのボタンを画像で表現したい場合、input
要素のtype
属性をimage
にしますが、button
要素を使うこともできます。src
属性とalt
属性を使うinput
要素と異なり、button
要素は
<button type="submit"><img src="btn.png" alt="送信" /></button>
のように要素の内容を持てるので、画像とテキストを両方含められる、JavaScriptで動作するボタン(type="button"
)も画像で表現できるなど自由度が高いです。
ただし、CSSでのスタイル当てにはいくつか注意しなくてはいけないことがあります。また、input
要素による画像ボタンは HTML 2.0(RFC1866) で既に定義されていたのに対し、button
要素は HTML 4.0 で登場したこともあり、古いブラウザ(IE6, 7)での対応状況が芳しくないので解決法を探ってみました。
リセットスタイルを書く
デフォルト状態だとpadding
やborder
が設定されていますが、文字だけのボタンはともかく画像ボタンでは不要なケースが多いのでリセットします。
button {
padding: 0;
border: none;
background: transparent;
}
button img {
display: block;
}
img
要素に display: block;
しているのは画像の下に空きができるのを防ぐためです。button
要素に対して line-height: 0;
でも空きは消えますが、代替テキストが表示される場合(画像が読み込まれない場合)のことを考えると好ましくありません。一方でボタン内に画像とテキストを両方含む場合などは改行されてしまうので、別の方法をとる必要があります。
また、 Internet Explorer と Opera はボタンを押下したときに数ピクセル右下に動きます。いかにもボタンを"押した"感がありますが、もし好ましくない場合は :active
疑似クラスを使って無効化します。
button:active,
button img {
position: relative;
}
button
要素の中身(img
要素)にも指定しているのはIE8以下のためです。サポート対象がIE9以上の場合はbutton:active
のみで大丈夫です。
Firefoxの ::-moz-focus-inner
上記のリセットスタイルだけでは、Firefoxのみ依然空きが残ります。
button
とinput[type="image"]
での描画比較(分かりやすいように赤背景を設定)これは ::-moz-focus-inner
という疑似要素が設定されているためで、MDNにはこんなことが書いてあります。
Firefox はアクセシビリティの観点から、フォーカスされたボタンに小さな点線ボーダーを表示するようになっています。このボーダーはブラウザのデフォルト・スタイルシートで宣言されています。これは次の様なセレクタを用い、あなた自身のスタイルで上書きする事が出来ます。
button::-moz-focus-inner { }
developer.mozilla.org
)
ということで、スタイルを追加します。
button::-moz-focus-inner {
padding: 0;
border: none;
}
しかし、こうするとキーボード操作でボタンにフォーカスを合わせたときに何の変化も起きないので、ユーザーは今どこにフォーカスがあるのか分からなくなってしまいます。MDNでも念を押すようにアクセシビリティに配慮したスタイリングを心がけて下さい。
(developer.mozilla.org
)と言っていることですし、何らかのスタイルを当てた方が良いでしょう。例えばアウトラインを出すにはこうします。
button:moz-focusring {
outline: 1px dotted #000;
}
2017年5月1日追記ここのサンプルは button:focus
としていたのですが、 Chrome などではデフォルトで青い実線アウトラインになるところ、この指定によってボタンだけアウトラインのスタイルが変わってしまうため、 Firefox でのみ適用される:-moz-focusring
疑似クラス(developer.mozilla.org
)へ変更しました。
Internet Explorer 6, 7 の挙動
button
要素内側の空きを消す
IE7でもボタンの内側に空きが残ります。
button
とinput[type="image"]
での描画比較(分かりやすいように赤背景を設定)これはbutton
要素に画像と同じ幅と高さを指定すれば消えました。
button {
padding: 0;
border: none;
*width: 44px; /* for IE6-7 */
*height: 50px; /* for IE6-7 */
background: transparent;
}
ただしこうすると、画像が表示されない場合に代替テキストが途中で切れてしまう恐れがあります。あまり好ましくないので、IE8や他のブラウザでは無視されるような指定をした方が良いでしょう。この例ではいわゆるアスタリスクハックをしています。
type
属性のデフォルト値はbutton
type
属性には submit
, button
, reset
の3種類を指定することができますが、type
属性を指定しなかった場合のデフォルト値は submit
です。なので仕様上、送信ボタンの場合はtype
属性を省略できることになりますが、IE7以下はbutton
と判定されてしまい、押しても何も起こりません。MSDNには以下の記述があります。
In IE8 Standards mode, the default value is submit. In other compatibility modes and earlier versions of Windows Internet Explorer, the default value is button.
msdn.microsoft.com
)
これの対処は簡単で、type
属性を省略しなければ問題ありません。
ボタンに名前を付けた場合
送信ボタンには名前と初期値を設定することができます。input
要素による画像ボタンではvalue
属性を指定することができないので、フォーム内に複数のボタンがあるときにどのボタンが押されたかを名前でなく値で判別したい場合など、button
要素の採用が大きなメリットとなります。
ところが、IE7以下はvalue
属性値でなくbutton
要素の中身をテキストとして送信してしまいます。つまりこんなHTMLの場合、
<button type="submit" name="btn" value="1"><img src="btn.png" alt="送信" /></button>
本来なら btn=1
が送られるのが正しいのですが、IE7以下は btn=<IMG alt=送信 src="btn.png">
となってしまいます。
- 実際にはこれをURLエンコードした値となります。
これもMSDNに記載がありますね。
When the BUTTON element is submitted in a form, the value depends on the current document compatibility mode. In IE8 mode, the value attribute is submitted. In other document modes and earlier versions of Internet Explorer, the innerText value is submitted.
msdn.microsoft.com
)
IE6は複数ボタンを置けない
さらにIE6は、フォーム内に複数の送信ボタンがあった場合に、名前の付いたすべてのbutton
要素の値を送信してしまうというバグが存在します。これではサーバー側で判別することができません。ひどいですね…。
結論としては、フォーム内に複数の送信ボタンが必要なケースでは、button
要素を使うのは時期尚早と言えます。レイアウトが崩れるといった些細な問題ではなく、正しい送信処理ができないことにもなるので、IE6が絶滅するまで(少なくとも Microsoft が Windows XP の延長サポートを終了する来年4月まで)は一般のウェブサイトでは採用すべきでないでしょう。また、IE7でも値(value
)での判別ができないなどの制約があります。
一方で送信ボタンがひとつの場合や type="button"
なボタンで使用する分には、送信ボタンであってもtype
属性を省略しないこと、またFirefoxの ::-moz-focus-inner
に対する対処方法などを知っていれば使用に大きな問題はないと思います。
- なお、本記事におけるボタン画像はブログランキング用ぽちっとなボタン | デザイナー佐脇の気ままな日記(
www.d-31n.com
)より拝借しました。