ファイルを添付 (=アップロード) できるような
フォームを作る時には input[type=file] を使います。
↓こういうやつです。
これはこれで良いのですが、
装飾したり、デザインを適用したい
という場面があるかもしれません。
input[type=file] は Webブラウザ毎に表示が異なり
意図したデザインを適用することもちょっと難しいです。
ありがちな落とし穴として
- input[type=file]
- デザインされた『ボタン』
を個別に用意して『ボタン』が押された時に
Javascript で input[type=file] をクリックする…
というような作りにするとハマります。
IE8 では動かなくなります。
IE8 で機能しない典型例 (1)
Javascript で間接的に input[type=file] を
クリックする例を考えてみます。
具体的には以下のような感じです。
コードは以下のような感じです。
<input type="file" id="article-537-file-chooser-1" style="display:none;" />
<button onclick="document.getElementById('article-537-file-chooser-1').click();">デザインされたボタン</button>
この中で button要素にスタイルを適用すれば
意図しているフォームが作れるように思えます。
実際、 IE でなければ意図通り完璧に動作します。
しかし、このような作りは IE8 では機能しません。
ちゃんと POST が出来なくなります。
よしんば POST したとしても
ファイルは空になります。
IE8 で機能しない典型例 (2)
On IE8 file upload fails when triggered indirectly by a button #251
で述べられているように、
Microsoft のセキュリティ対策により
IE8 では input[type=file] を
間接的にクリックしてファイルをアップロード
しようとしても POST できません。
IE8 では Webブラウザのデフォルトの
input[type=file] をユーザ自らが
直接クリックしなければなりません。
また、ユーザがクリックできるためには
スタイル上は可視状態でなければなりません。
つまり、以下のような状態では問題が生じます。
- display: none;
- visibility: hidden;
以下は目視はできませんが、可視扱いです。
- opacity: 0;
- position の指定で画面外…
ということは、 CSS をいくらかトリッキーに使って
透明な input[type=file] を被せるか、
label を使うか、あまり実装の選択肢はありません。
仮に label を使う場合、
その内部に input などを置く訳にはいきません。
ですから、マウスオーバーやクリックへの
フィードバックを考えるとちょっと面倒です。
フィードバックという点では、 a要素に
マウスカーソルをのせたりタップした際に
何らかのフィードバックを持たせていることがあります。
そのような場合、これを再利用しようと a要素を
label内に置くと意図した動作が得られません。
<input type="file" id="article-537-file-chooser-2" style="position:absolute; left:-999px; top:-999px;" />
<label for="article-537-file-chooser-2"><a class="btn" href="javascript:void(0);">デザインされたボタン</a></label>
美しくはないけれど、とりあえず何とかする
<div style="position:relative; overflow:hidden; height:34px; width:162px;">
<input type="file" id="article-537-file-chooser-3" style="position:absolute; left:-999px; opacity:0;" /><label for="article-537-file-chooser-3"><span style="border:1px solid #777; background:#ccc; border-radius:4px; display:block; line-height:32px;height:32px; width:160px; text-align:center;">デザインされたボタン</span></label>
</div>
ラッパーを作ってその中に input[type=file] と
それをクリックする label を置きます。
ラッパーには
- overflow: hidden;
- position: relative;
を設定します。
input[type=file] は
position:absolute; にして視界外へ、
label の中にはボタンのデザインを施した
span要素を置きます。
美しくはないのですが、
IE8 と input[type=file] とデザインを
共存させるときのヒントになれば幸いです。
お問い合わせについて
業務として技術コンサルティングやシステム設計・開発を行っております。
気になることがありましたらご相談下さい。
ご相談のみで完結する場合、コンサルティング費用の目安は
内容によりますが1時間で5千円〜1万円ていどです。
コンサルティングや開発を検討されるその前に、
まずはお気軽にコメントやメールでご連絡下さい。
※ご契約前のコメントやメールでのやりとりは無料です。