2024年版を書きました
bootstrapを使ってファイルをアップロードするフォームをつくるとき、デフォルトのボタンは小さくて、特にスマホでは表示する際に使いにくいと感じます
こちらの投稿でBootstrap File Inputを使った方法が紹介されています。見た目だけでなく、機能も豊富で参考になります。
ただ今回はbootstrap標準デザインのボタンを使う方法を紹介します。
こちらを参考にしました。
標準の<input type="file">
まず標準の<input type="file">の確認です
<input type="file">
これです。
<span class="btn">で囲んでボタンにする
spanタグで囲むことでbootstrap標準デザインのボタンにできます。inputはstyle="display:none"
で隠します。
<span class="btn btn-primary">
Choose File
<input type="file" style="display:none">
</span>
このようになります。
ただ、これではクリックしてもファイルを選択できません(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>
まだファイルを選んでも何も表示されません。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;
}
こうなります。
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>
追記
最近のBootstrapではjqueryがデフォルトでは動作しないため、別の対策が必要です