Twitter Bootstrap表单文件元素上传按钮

610
为什么Twitter Bootstrap没有华丽的文件上传按钮?如果使用蓝色主要按钮来实现上传按钮会很棒。通过CSS调整上传按钮是否可行?(看起来像是无法操作的本地浏览器元素)

13
你可以在这里找到它:http://markusslima.github.io/bootstrap-filestyle/。 - rh0dium
27个回答

1027

以下是 Bootstrap 3、4 和 5 的解决方案。

要创建一个看起来像按钮的功能性文件输入控件,只需要使用 HTML:

HTML

<label class="btn btn-default">
    Browse <input type="file" hidden>
</label>

这在所有现代浏览器中都可以使用,包括IE9+。如果你需要支持旧版本的IE,请使用下面展示的传统方法。

该技术依赖于HTML5中的 hidden 属性。Bootstrap 4 使用以下CSS来为不支持它的浏览器提供支持。如果你正在使用Bootstrap 3,你可能需要添加。

[hidden] {
  display: none !important;
}

为旧版IE使用传统方法

如果你需要支持IE8及以下版本,请使用以下HTML/CSS代码:

HTML

<span class="btn btn-default btn-file">
    Browse <input type="file">
</span>

CSS

.btn-file {
    position: relative;
    overflow: hidden;
}
.btn-file input[type=file] {
    position: absolute;
    top: 0;
    right: 0;
    min-width: 100%;
    min-height: 100%;
    font-size: 100px;
    text-align: right;
    filter: alpha(opacity=0);
    opacity: 0;
    outline: none;
    background: white;
    cursor: inherit;
    display: block;
}

请注意,旧版IE在单击<label>时不会触发文件输入,因此The CSS“膨胀”需要采取以下措施来解决:

  • 使文件输入跨越周围<span>的整个宽度/高度
  • 使文件输入不可见

反馈和进一步阅读

我发布了更多关于该方法的详细信息以及示例,展示如何向用户显示选择了哪些/多少个文件:

https://www.abeautifulsite.net/posts/whipping-file-inputs-into-shape-with-bootstrap-3/


56
对我而言,这绝对是最好的答案。使用最新版本的Bootstrap提供了非常简洁的解决方案。 - Ulises
7
@Ulises @JaredEitnier @IvanWang 我非常尊重地不同意。并且我会毫不掩饰地推荐我的答案,它只是使用了<label>元素。作为最佳解决方案 :) - Kirill Fuchs
10
我同意@KirillFuchs的观点,标签会更好。此外,用户无法看到他们选择的正确文件,因为按钮不显示所选文件的名称:https://jsfiddle.net/36o9pdf9/1/ - danwild
1
我无法在IE11中与FormData对象一起使用此功能。不知何故,当输入字段位于标签元素内部时,IE会忽略它,因此文件数据无法从FormData对象中获取。 - René
1
谢谢您的帖子,它帮助我清理了使用输入文件元素的网站的样式。然而,我在.btn-file input[type=file]规则中遇到了一个问题,即font-size: 100px属性在页面上通过输入元素进行制表时会出现问题。将此属性的值更改为10px解决了我的问题。不确定这是否只是一个打字错误还是故意设置的,但想分享一下。干杯。 - Anil
显示剩余24条评论

409

我很惊讶没有提到<label>元素。

解决方案:

<label class="btn btn-primary" for="my-file-selector">
    <input id="my-file-selector" type="file" class="d-none">
    Button Text Here
</label>

不需要任何JS或花哨的CSS...

包含文件名的解决方案:

<label class="btn btn-primary" for="my-file-selector">
    <input id="my-file-selector" type="file" style="display:none" 
    onchange="$('#upload-file-info').text(this.files[0].name)">
    Button Text Here
</label>
<span class='label label-info' id="upload-file-info"></span>

以上解决方案需要使用jQuery。

注意:在页面上显示用户提供的内容时,请使用$.text()。此答案的早期版本使用了$.html(),这是不安全的——文件名可能包含HTML标记。


44
这个回答应该被采纳。它甚至比@claviska的回答更好。 - Fernando Carvalhosa
4
为什么这个回答没有被采纳,我不太明白。它简洁、简单、稳定(除非你的目标浏览器是IE9及以下版本……) - Jake Foster
25
好的,它没有显示选择了哪个文件。 - godblessstrawberry
3
如果你用 label 包裹目标元素,就不需要使用 for。 - 0xcaff
3
我对它进行了微调,以仅显示文件名而不包括"C://fakepath",代码如下:onchange="$('#upload-file-info').html(this.files[0].name);" - Sincere
显示剩余18条评论

136

没有需要额外插件的要求,这个Bootstrap解决方案对我来说非常有效:

<div style="position:relative;">
        <a class='btn btn-primary' href='javascript:;'>
            Choose File...
            <input type="file" style='position:absolute;z-index:2;top:0;left:0;filter: alpha(opacity=0);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0;background-color:transparent;color:transparent;' name="file_source" size="40"  onchange='$("#upload-file-info").html($(this).val());'>
        </a>
        &nbsp;
        <span class='label label-info' id="upload-file-info"></span>
</div>

演示:

http://jsfiddle.net/haisumbhatti/cAXFA/1/(Bootstrap 2)

输入图像说明

http://jsfiddle.net/haisumbhatti/y3xyU/(Bootstrap 3)

输入图像说明


6
我遇到了按钮底部区域无法点击的问题。这个答案对我在bootstrap 3中的帮助很大:https://dev59.com/8Wgu5IYBdhLWcg3wkHyP#18164555 - Paul Lemke
3
这是一个很棒的解决方案,因为它显示了所附文件的文件名! - cb88
2
有人能解释一下 href='javascript:;' 的必要性吗?我不需要 onchange='$("#upload-file-info").html($(this).val());' 来更新 upload-file-info 元素,但是如果没有 href,文件上传对话框就无法触发。 - user12121234
2
'C:\fakepath'是从哪里来的,我该如何摆脱它? - Ya.
1
@Ya。C:\fakepath是HTML5的安全特性,如果我们使用JavaScript操作文件路径,则会在文件路径前加上它。请参阅此博客文章http://davidwalsh.name/fakepath了解详情。 - codefreak
“2个文件”等是否支持多文件? - msj121

90

这个已经包含在Jasny的Bootstrap分支中。

可以使用以下方式创建一个简单的上传按钮:

<span class="btn btn-file">Upload<input type="file" /></span>

使用fileupload插件,您可以创建更高级的小部件。请查看 http://jasny.github.io/bootstrap/javascript/#fileinput


这个在IE9中可以正常工作吗?我问这个问题是因为我假设这个解决方案使用了Javascript,而且同时,“由于安全原因,IE不允许通过Javascript操作type =”file“输入元素。” - Marek Příhoda
是的,它也适用于IE9。它将输入元素的不透明度设置为0,幸运的是在所有浏览器中都有效 :)。这在quirksmode文章中有解释。 - Arnold Daniels
1
它不支持jQuery 1.9.0,因为它们放弃了$.browser的支持。 - Giedrius
14
使用普通的Bootstrap样式看起来很糟糕 - http://img688.imageshack.us/img688/948/pictureui.png - cwd

66

上传按钮很难进行样式设计,因为样式应用于输入框而不是按钮。

但是你可以使用以下技巧:

http://www.quirksmode.org/dom/inputfile.html

总结:

  1. 将一个普通的 <input type="file"> 放置到一个带有 position: relative 的元素中。

  2. 在这个相同的父元素中,添加一个普通的 <input> 和一张图片,它们具有正确的样式。将这些元素绝对定位,使它们占据与 <input type="file"> 相同的位置。

  3. <input type="file"> 的 z-index 设置为 2,这样它就位于样式化的输入框/图片之上。

  4. 最后,将 <input type="file"> 的透明度设置为 0。现在,<input type="file"> 成为实际上不可见的,而样式化的输入框/图片则显示出来,但你仍然可以单击“浏览”按钮。如果按钮位于图片的顶部,用户似乎会单击图片并获取正常的文件选择窗口。(请注意,你不能使用 visibility: hidden,因为一个真正不可见的元素也是不可单击的,我们需要让该元素保持可点击状态)


6
这对现在来说是太多工作了。使用像Jasny的解决方案那样的现成工具会更加明智。 - mgPePe
2
如果你的示例包含支持Netscape的内容,那么它可能已经过时了。 - Typhomism

22

对我来说可行:

更新

jQuery插件风格

// Based in: http://duckranger.com/2012/06/pretty-file-input-field-in-bootstrap/
// Version: 0.0.3
// Compatibility with: Bootstrap 3.2.0 and jQuery 2.1.1
// Use:
//     <input class="nice_file_field" type="file" data-label="Choose Document">
//     <script> $(".nice_file_field").niceFileField(); </script>
//
(function( $ ) {
  $.fn.niceFileField = function() {
    this.each(function(index, file_field) {
      file_field = $(file_field);
      var label = file_field.attr("data-label") || "Choose File";

      file_field.css({"display": "none"});

      nice_file_block_text  = '<div class="input-group nice_file_block">';
      nice_file_block_text += '  <input type="text" class="form-control">';
      nice_file_block_text += '  <span class="input-group-btn">';
      nice_file_block_text += '   <button class="btn btn-default nice_file_field_button" type="button">' + label + '</button>';
      nice_file_block_text += '  </span>';
      nice_file_block_text += '</div>';

      file_field.after(nice_file_block_text);

      var nice_file_field_button = file_field.parent().find(".nice_file_field_button");
      var nice_file_block_element = file_field.parent().find(".nice_file_block");

      nice_file_field_button.on("click", function(){ console.log("click"); file_field.click() } );
      file_field.change( function(){
        nice_file_block_element.find("input").val(file_field.val());
      });
    });
  };
})( jQuery );

18

从其他答案中提取部分内容简明回答,主要来源是user2309766和dotcomsuperstar。

特点:

  • 使用Bootstrap按钮附加项用于按钮和字段。
  • 只有一个输入框;多个输入框将被表单捕获。
  • 除了“display: none;”以隐藏文件输入之外,没有额外的css。
  • 可见按钮触发隐藏文件输入的点击事件。
  • split使用正则表达式和分隔符'\'和'/'来删除文件路径。

代码:

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div class="input-group">
  <span class="input-group-btn">
    <span class="btn btn-primary" onclick="$(this).parent().find('input[type=file]').click();">Browse</span>
    <input name="uploaded_file" onchange="$(this).parent().parent().find('.form-control').html($(this).val().split(/[\\|/]/).pop());" style="display: none;" type="file">
  </span>
  <span class="form-control"></span>
</div>


13

参考其他上面的帖子,这里提供一个完整的解决方案,将form-control字段与input-group-addon结合起来,创建一个干净的文件输入小部件,其中包括指向当前文件的链接。

.input-file { position: relative; margin: 60px 60px 0 } /* Remove margin, it is just for stackoverflow viewing */
.input-file .input-group-addon { border: 0px; padding: 0px; }
.input-file .input-group-addon .btn { border-radius: 0 4px 4px 0 }
.input-file .input-group-addon input { cursor: pointer; position:absolute; width: 72px; z-index:2;top:0;right:0;filter: alpha(opacity=0);-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";opacity:0; background-color:transparent; color:transparent; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<div class="input-group input-file">
  <div class="form-control">
    <a href="/path/to/your/current_file_name.pdf" target="_blank">current_file_name.pdf</a>
  </div>
  <span class="input-group-addon">
    <a class='btn btn-primary' href='javascript:;'>
      Browse
      <input type="file" name="field_name" onchange="$(this).parent().parent().parent().find('.form-control').html($(this).val());">
    </a>
  </span>
</div>


9
请查看Twitter Bootstrap文件输入。它使用非常简单的解决方案,只需添加一个JavaScript文件并粘贴以下代码:
$('input[type=file]').bootstrapFileInput();

链接已失效(2019年7月)。 - Yetti99
@Yetti99 是的,它现在已经坏了。 - monsur.hoq
@Yetti99,我已经更改了链接,请现在检查一下。 - monsur.hoq

9

这对我来说完美地运作。

<span>
    <input  type="file" 
            style="visibility:hidden; width: 1px;" 
            id='${multipartFilePath}' name='${multipartFilePath}'  
            onchange="$(this).parent().find('span').html($(this).val().replace('C:\\fakepath\\', ''))"  /> <!-- Chrome security returns 'C:\fakepath\'  -->
    <input class="btn btn-primary" type="button" value="Upload File.." onclick="$(this).parent().find('input[type=file]').click();"/> <!-- on button click fire the file click event -->
    &nbsp;
    <span  class="badge badge-important" ></span>
</span>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接