input要素のtype=”file”を装飾する方法
こんにちは、Sonicmoov勤続5年弱のだってぃです。
いや~時がながれるのって本当に早いですね。
すっかりお局・・・いや、お局の男バージョンの言葉ってないんですかね?
まぁいい。別にお局でもいいや。
人生絶賛迷子中です。
気が付けば前回の記事「select要素を装飾するいくつかの方法」を書いてから1年半たっていますね。
・・・あれ?弊社のこのLab、人数的に考えて、半年に1度くらいは回ってくるはず
・・・ うん、まぁよしとしよう。もみ消そう!HAHAHA!
はい、今日は前回に引き続きフォーム関連要素の装飾のお話。
あの不可侵領域、input要素のtype=”file”の装飾方法をチェケラします。
デザイン変更できちゃうんですよ、実は。
ん?タイトル横の画像と内容が関係ないって?
はい、だって、ほら、input type=”file”っぽい画像って何?って感じですし。
でもアイキャッチ的な画像はあった方がいいって、たくさんの偉い人達が言ってますし。
しょうがないね。
まぁそれはいいとして、
が
になっちゃうんですよ!
素敵!!!!
その1.
Javascriptでinput type=”file”要素のイベントを・・・する方法
結論からいいます、この方法はダメです。
なぜならばIEで動かない。
いや、一見動いているようにみえて実は・・・
フォーム送信されたときに値が入ってこない!!!
No more IE!!
No more IE!!!!
・・・・まぁでもこの方法の方が、楽ちん(そうか?)だし、まっとうな方法だと思うので、紹介するだけしておきます。
ざっくり手順
- 「ダミーとなるテキストフィールド(readonly)とボタン」実体となるinput type=”file”を配置。
- input type=”file”を非表示(display=”none”)
- javascriptでボタンと実体のクリックイベントをつなぎこみ
まぁ実際は値を取る手順があるのですが、考え方だけなら上記のとおりです。
あとはソースを見てもらった方が早い。
いや、違う、面倒くさいとかそうじゃなくて・・・そうじゃなくて・・・
はい、以下。
HTML
※わかりやすいように余計なタグはいれてません。
1 2 3 4 5 6 7 |
[sourcecode lang="html"] <div class="fileUploder"> <input type="text" class="txt" readonly> <button class="btn">参照</button> <input type="file" class="uploader"> </div> [/sourcecode] |
CSS
※わかりやすいように装飾系の指定はいれてません。
1 2 3 4 5 |
[sourcecode lang="css"] .fileUploder .uploader{ display:none; } [/sourcecode] |
Javascript
※jQuery使ってます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
[sourcecode lang="javascript"] $(function(){ fileUploader(); }); var fileUploader = function(){ var self = this; //ラッパーのdiv var target = $('.fileUploder'); //ボタンをクリックしたら、実体の方を起動 this.setBtn = function(btn,txt,uploader){ btn.bind('click',function(event){ //イベントキャンセル event.preventDefault(); //実体をクリックしたことに uploader.click(); //テキストフィールドに値をいれる self.setTxt(txt,uploader); //一応モダンじゃないブラウザ用 return false; }); } //テキストフィールドに値をいれる this.setTxt = function(txt,uploader){ var timer = setTimeout(function(){ //テキストフィールドに値が入っている時 if(txt.val().length > 0){ //タイマーをとめる clearTimeout(timer); } //テキストフィールドに値が入っていない時 else{ //実体の値を取得して、テキストフィールドに入れる txt.val(uploader.val()) //もう一度実行 self.setTxt(txt,uploader); } },500) } //イベント割り当て target.each(function(){ //ダミーのテキストフィールド var txt = $(this).find('.txt'); //ファイルアップロードボタン var btn = $(this).find('.btn'); //input[type=file]の実体 var uploader = $(this).find('.uploader'); //ボタンのイベントをセット self.setBtn(btn,txt,uploader); }); } [/sourcecode] |
※jsはパパっと適当に書いたので、導入の際は自己流でやってみたほうがいいかも☆
その2.
input type=”file”を透明にして上にかぶちゃう
はい、こちらが本命。
本命の情報を後にもってきてしまった。
じらしテク。
ざっくり手順
- ダミーとなるテキストフィールド(readonly)とボタン、実体となるinput type=”file”を配置。
- ラッパーのdivをposition:relativeにして、適切な幅(デザイン依存)指定
- input type=”file”を絶対配置(position:absolute)にして、幅・高さを100%にしてラッパーのdivを覆い、透明化
- javascriptでinput type=”file”のonchangeイベントを拾い、ダミーのテキストフィールドに値をセット。
HTML
とりあえずHTMLはこんなん。
※その1と同じものです。
1 2 3 4 5 6 7 |
[sourcecode lang="html"] <div class="fileUploder"> <input type="text" class="txt" readonly> <button class="btn">参照</button> <input type="file" class="uploader"> </div> [/sourcecode] |
CSS
つぎにCSS・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
[sourcecode lang="css"] .fileUploder{ position:relative; /*↓幅はデザイン依存。場合によっては、指定しなくていい*/ width:315px; } .fileUploder .uploader{ position:absolute; top:0; right:0; /*↓念のため*/ z-index:99; width:100%; height:100%; opacity:0; } [/sourcecode] |
これでいいはずだった・・・
そう・・・あいつさえいなければ・・・・
・・・・IE!!!
No more IE!!
No more IE!!!!
さて、IEの何が問題かというのを順を追ってみていきましょう。
まず、わかりやすいように上記のCSSの状態でopacity:0をとったものをIEでみてみましょう。
おぉ・・・しっかりきっちりラッパーのdivに覆いかぶさって表示されてますね(わかりにくいけど)。
でも・・・でもね・・・・
なんてこったい!!!!
なんで!なんでだよ、IE!!!!
ちなみにダブルクリックすれば、エクスプローラーが立ち上がります。
なんなんだその仕様。
てなわけで、IEは幅を指定しただけでは対応ができないんですよ、困ったことに。
さて、この問題をどう解決するかといいますと。
それは、ずばり!
font-size
です。
では実際にCSSを書き換えてみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[sourcecode lang="css"] .fileUploder{ position:relative; /*↓幅はデザイン依存。場合によっては、指定しなくていい*/ width:315px; /*↓はみ出した分隠す*/ overflow:hidden; } .fileUploder .uploader{ position:absolute; top:0; /*↓leftからrightに。ボタンが右にあるので、rightにしないとだめ。IE対策。*/ right:0; /*↓念のため*/ z-index:99; width:100%; height:100%; /*↓ここでフォームアイテムの大きさを調整。IE対策*/ font-size:80px; } [/sourcecode] |
これをIEで見ると。
わかりにくいですが、確かに拡大されてます。
参照ってボタンの上がちょっと見えてるので、それでわかると思います。
ここでは、わかりやすいように80pxとしましたが、それだとまだクリックで反応しない部分が、かぶってきてしまっています。
なので、ここは思い切ってラッパーのdivの幅くらいのfont-sizeを指定してしまいましょう。
思いきり、大事。
人生と一緒ですね。
まさかのIEの壁を乗り越えた完全版CSSソースが以下!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
[sourcecode lang="css"] .fileUploder{ position:relative; /*↓幅はデザイン依存。場合によっては、指定しなくていい*/ width:315px; /*↓高さ指定しないとIE7で領域がひろがる…?*/ height:31px; /*↓はみ出した分隠す。IE対策*/ overflow:hidden; } .fileUploder .uploader{ position:absolute; top:0; /*↓leftからrightに。ボタンが右にあるので、rightにしないとだめ。IE対策。*/ right:0; /*↓念のため*/ z-index:99; width:100%; height:100%; /*↓ここでフォームアイテムの大きさを調整。IE対策*/ font-size:315px; opacity:0; /*↓IE6,7対策*/ filter:alpha(opacity=0); /*↓IE8対策*/ -ms-filter:"alpha(opacity=0)"; } [/sourcecode] |
これで、CSSはOKです。
細かい部分は要件によって変えてくださいませ。
Javascript
最後にjavascriptはまぁちゃちゃっと。
その1と違うのは実体のonchangeでやってるってことですかね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
[sourcecode lang="javascript"] $(function(){ fileUploader(); }); var fileUploader = function(){ //ラッパーのdiv var target = $('.fileUploder'); //イベント割り当て target.each(function(){ //ダミーのテキストフィールド var txt = $(this).find('.txt'); //ファイルアップロードボタン var btn = $(this).find('.btn'); //input[type=file]の実体 var uploader = $(this).find('.uploader'); //実体が変更された時 uploader.bind('change',function(){ //テキストフィールドに値をいれる txt.val($(this).val()); }); //ボタンのイベントは無効にしておく btn.bind('click',function(event){ //イベントキャンセル event.preventDefault(); //一応モダンじゃないブラウザ用 return false; }); //ホバー処理(上にかぶせているので反応しないため) //ここはデザインの都合上いれている処理のため適宜変更を //class切り替えでやったほうがいいです。 $(this).bind('mouseover',function(){ btn.css('background-position','0 100%'); }); $(this).bind('mouseout',function(){ btn.css('background-position','0 0'); }); }); } [/sourcecode] |
※jsはパパっと適当に書いたので(ry
おわりに
なんというか、やはり時代が流れようともIEとの泥臭い戦いは終わらないわけで。
XPのサポートが打ち切られても、IE8を完全に無視できるようになるのはいつの日か・・・
まぁ頑張っていきましょうねてなことで。
あと3か月でアラフォー突入のだってぃがお伝えしました~。
またいつか~~~~☆ミ
・・・・アラフォー・・・・(´・ω・`)