Help us understand the problem. What is going on with this article?

Bootstrapのファイルをアップロードするボタンを標準デザインのボタンにする

More than 1 year has passed since last update.

bootstrapを使ってファイルをアップロードするフォームをつくるとき、デフォルトのボタンは小さくて、特にスマホでは表示する際に使いにくいと感じます

こちらの投稿Bootstrap File Inputを使った方法が紹介されています。見た目だけでなく、機能も豊富で参考になります。

ただ今回はbootstrap標準デザインのボタンを使う方法を紹介します。

こちらを参考にしました。


標準の<input type="file">

まず標準の<input type="file">の確認です

<input type="file">

Screen Shot 2016-12-04 at 9.09.52 PM.png

これです。


<span class="btn">で囲んでボタンにする

spanタグで囲むことでbootstrap標準デザインのボタンにできます。inputはstyle="display:none"で隠します。

<span class="btn btn-primary">
    Choose File
    <input type="file" style="display:none">
</span>

Screen Shot 2016-12-04 at 9.40.15 PM.png

このようになります。

ただ、これではクリックしてもファイルを選択できません(Google Chromeで試しました)

さらにlabelタグで囲むと選択できるようになります。コードは下記のようになります。

<label>
    <span class="btn btn-primary">
        Choose File
        <input type="file" style="display:none">
    </span>
</label>

ファイル名を表示する

text-inputを使ってファイル名を表示します。下記のコードをみてください。

<div class="input-group">
    <label class="input-group-btn">
        <span class="btn btn-primary">
            Choose File<input type="file" style="display:none">
        </span>
    </label>
    <input type="text" class="form-control" readonly="">
</div>

Screen Shot 2016-12-04 at 10.57.20 PM.png

まだファイルを選んでも何も表示されません。jqueryを使ってファイル名を表示できるようにします

$(document).on('change', ':file', function() {
    var input = $(this),
    numFiles = input.get(0).files ? input.get(0).files.length : 1,
    label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
    input.parent().parent().next(':text').val(label);
});

おまけ:プレビューを表示する

画像を選択した際にプレビュー表示します。こちらを参考にしました

プレビューを表示するためのdivタグを追加します

<div class="imagePreview"></div>
<div class="input-group">
    <label class="input-group-btn">
        <span class="btn btn-primary">
            Choose File<input type="file" style="display:none" class="uploadFile">
        </span>
    </label>
    <input type="text" class="form-control" readonly="">
</div>
.imagePreview {
    width: 100%;
    height: 180px;
    background-position: center center;
    background-size: cover;
    -webkit-box-shadow: 0 0 1px 1px rgba(0, 0, 0, .3);
    display: inline-block;
}

Screen Shot 2016-12-04 at 10.36.10 PM.png

こうなります。

FileReaderを使って画像を読み込み、divの背景に表示します

$(document).on('change', ':file', function() {
    var input = $(this),
    numFiles = input.get(0).files ? input.get(0).files.length : 1,
    label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
    input.parent().parent().next(':text').val(label);

    var files = !!this.files ? this.files : [];
    if (!files.length || !window.FileReader) return; // no file selected, or no FileReader support
    if (/^image/.test( files[0].type)){ // only image file
        var reader = new FileReader(); // instance of the FileReader
        reader.readAsDataURL(files[0]); // read the local file
        reader.onloadend = function(){ // set image data as background of div
            input.parent().parent().parent().prev('.imagePreview').css("background-image", "url("+this.result+")");
        }
    }
});

後半を追記しています。


サンプル

html全体は下記です。試してみてください

<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style>
    .imagePreview {
        width: 100%;
        height: 180px;
        background-position: center center;
        background-size: cover;
        -webkit-box-shadow: 0 0 1px 1px rgba(0, 0, 0, .3);
        display: inline-block;
    }
</style>
    </head>
    <body>
        <div class="container page-header">
            <div class="col-sm-4">
                <form action="" method="post" enctype="multipart/form-data">
                    <div class="imagePreview"></div>
                    <div class="input-group">
                        <label class="input-group-btn">
                            <span class="btn btn-primary">
                                Choose File<input type="file" style="display:none" class="uploadFile">
                            </span>
                        </label>
                        <input type="text" class="form-control" readonly="">
                    </div>
                </form>
            </div>
        </div>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
        <script>
        $(document).on('change', ':file', function() {
            var input = $(this),
            numFiles = input.get(0).files ? input.get(0).files.length : 1,
            label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
            input.parent().parent().next(':text').val(label);

            var files = !!this.files ? this.files : [];
            if (!files.length || !window.FileReader) return; // no file selected, or no FileReader support
            if (/^image/.test( files[0].type)){ // only image file
                var reader = new FileReader(); // instance of the FileReader
                reader.readAsDataURL(files[0]); // read the local file
                reader.onloadend = function(){ // set image data as background of div
                    input.parent().parent().parent().prev('.imagePreview').css("background-image", "url("+this.result+")");
                }
            }
        });
        </script>
    </body>
</html>
Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away