如何自定义<input type="file">?

209

能否改变 <input type="file"> 元素的外观?


文本字段的存在是因为它可以在用户浏览并选择文件后显示文件路径。 - k to the z
哎呀,看来这是Firefox的处理方式... - Newbie Coder
只是为了明确,即使他们浏览文件后,仍然需要使用表单提交按钮提交表单。 - k to the z
18个回答

314

关于input[type=file]控件本身,你不能做很多修改。

由于单击已正确与输入配对的

以下是您可以执行的操作...

label {
   cursor: pointer;
   /* Style as you please, it will become the visible UI component. */
}

#upload-photo {
   opacity: 0;
   position: absolute;
   z-index: -1;
}
<label for="upload-photo">Browse...</label>
<input type="file" name="photo" id="upload-photo" />

表单控件的 CSS 将使其在文档布局中看起来是不可见的,也不占用空间,但仍然存在,以便可以通过

如果你想在选择后显示用户选择的路径,可以使用 JavaScript 监听change事件,然后读取浏览器提供的路径(出于安全原因,它可能向您虚假报告确切的路径)。一种使其对最终用户友好的方法是仅使用返回的路径的基本名称(因此用户仅看到所选文件的文件名)。

这里有一个由 Tympanus 编写的很棒的指南可供参考。


2
我认为,考虑到我们的目标是通过单击容器中的任何位置打开选择文件对话框,以下是更好的样式:#container { position: relative; width: ...px; height: ...px; overflow: hidden; } #input { position: absolute; right: 0; font-size: <many a>px; opacity: 0; margin: 0; padding: 0; border: none; } - x-yuri
2
使用<label>(如Tympanus所示)更具语义性,不那么hacky。此外,这个问题几年后又被问到了,并且有更好的答案:跨浏览器自定义文件上传按钮样式 - Dan Dascalescu
1
@DanDascalescu 我同意,如果我没记错的话(回到2011年),它在IE上有问题,可能是6或7。我现在会编辑这个答案,使其符合现在的情况。 - alex
为什么使用标签会更好呢?你不能通过制表符访问标签,此外,对我来说,使用按钮比标签更有意义,可以激活对话框。 - Mat
1
@alex,它没有显示文件名。 - Naren Verma
显示剩余2条评论

38

可能是这样吧?

<form>
  <input id="fileinput" type="file" style="display:none;"/>
</form>
<button id="falseinput">El Cucaratcha, for example</button>
<span id="selected_filename">No file selected</span>

<script>
$(document).ready( function() {
  $('#falseinput').click(function(){
    $("#fileinput").click();
  });
});
$('#fileinput').change(function() {
  $('#selected_filename').text($('#fileinput')[0].files[0].name);
});

</script>

1
在这种情况下,IE 9将不允许将表单发送到iframe。 - x-yuri
@x-yuri 你是什么意思? - Micaël Félix
2
据我所记,IE 9(可能还有其他浏览器)不允许将表单发送到iframe,因为用户没有点击input-file。 - x-yuri
2
display: none 会将输入框从选项卡顺序中移除,使页面的可访问性降低。使用 <label>(如 Tympanus 所示)更具语义性,更少 hacky。此外,这个问题几年后又被问到了,并且有更好的答案:跨浏览器自定义文件上传按钮样式 - Dan Dascalescu
修复了选择器中的右方括号错误,使代码实际可用。 - Constantin Groß

32
  <label for="fusk">dsfdsfsd</label>
  <input id="fusk" type="file" name="photo" style="display: none;">

为什么不呢?^_^

在这里查看示例here


4
@InakiIbarrolaAtxa,你能提供数据支持这个观点吗? - Ky -
3
在Chrome 51中不支持样式化文件上传控件。使用<label>(如Tympanus所示)是一种语义上正确的解决方案。此外,该问题在几年后被重新提出,并有更好的答案:跨浏览器自定义文件上传按钮样式 - Dan Dascalescu

21

我在使用Bootstrap时遇到了很多麻烦。在手机上,当我点击勾选完成照片的复选框时,表单会提交,但并没有上传照片,而不是等待提交按钮。目前我的代码如下:<label class="btn btn-default btn-file"> <input onchange="alert('Please check picture is OK')"; type="file" required> </label>,并且使用了一些JavaScript来检查必填字段,就像Bootstrap示例中的一样。 - Hugh Barnard

16

最简单的方法...

<label>
     Upload
    <input type="file" style="visibility: hidden;"/>
</label>

使用 style="display:none;"visibility:hidden 更好。 - medBouzid

13

技巧在于隐藏输入框并自定义标签。

在此输入图片描述

HTML:

<div class="inputfile-box">
  <input type="file" id="file" class="inputfile" onchange='uploadFile(this)'>
  <label for="file">
    <span id="file-name" class="file-box"></span>
    <span class="file-button">
      <i class="fa fa-upload" aria-hidden="true"></i>
      Select File
    </span>
  </label>
</div>

CSS:

.inputfile-box {
  position: relative;
}

.inputfile {
  display: none;
}

.container {
  display: inline-block;
  width: 100%;
}

.file-box {
  display: inline-block;
  width: 100%;
  border: 1px solid;
  padding: 5px 0px 5px 5px;
  box-sizing: border-box;
  height: calc(2rem - 2px);
}

.file-button {
  background: red;
  padding: 5px;
  position: absolute;
  border: 1px solid;
  top: 0px;
  right: 0px;
}

JS:

function uploadFile(target) {
    document.getElementById("file-name").innerHTML = target.files[0].name;
}

您可以查看此示例:https://jsfiddle.net/rjurado/hnf0zhy1/4/


10
在 Webkit 中,您可以尝试以下操作...
input[type="file"]::-webkit-file-upload-button{
   /* style goes here */
}

你知道 Firefox 的类似解决方案吗?它是否存在? - ventro_art

7

首先,它是一个容器:

<div class="upload_file_container">
    Select file!
    <input type="file" name="photo" />
</div>

第二点是CSS样式,如果您想进行更多的自定义,请保持警觉 :)
.upload_file_container{
   width:100px;
   height:40px;
   position:relative;
   background(your img);
}

.upload_file_container input{
   width:100px;
   height:40px;
   position:absolute;
   left:0;
   top:0;
   cursor:pointer;
}

这个例子没有为按钮内部的文本设置样式,它取决于字体大小,只需纠正容器的高度和padding-top值即可。


我想知道为什么你不把它设为 right: 0,而是 left: 0?这样你就可以将ie的文本框移出容器。点击文本框不会打开选择文件对话框。此外,我认为使用 font-size 来调整输入文件的大小比使用 widthheight 更好。 - x-yuri

7
这里有一个快速纯CSS解决方案(适用于Chrome,并包括FireFox备用方案),包括文件名、标签和自定义上传按钮,能够完美地实现功能 – 完全不需要JavaScript!请注意:☝无论如何,在实际网站上我不会使用它 - 如果浏览器兼容性对你很重要(应该是的话)。 因此,这更像是一种实验性的东西,否则随着时间的推移,今天这可能已经不是问题了。

.fileUploadInput {
  display: grid;
  grid-gap: 10px;
  position: relative;
  z-index: 1; }
  
  .fileUploadInput label {
    display: flex;
    align-items: center;
    color: setColor(primary, 0.5);
    background: setColor(white);
    transition: .4s ease;
    font-family: arial, sans-serif;
    font-size: .75em;
    font-weight: regular; }
    
  .fileUploadInput input {
    position: relative;
    z-index: 1;
    padding: 0 gap(m);
    width: 100%;
    height: 50px;
    border: 1px solid #323262;
    border-radius: 3px;
    font-family: arial, sans-serif;
    font-size: 1rem;
    user-select: none;
    cursor: pointer;
    font-weight: regular; }
    .fileUploadInput input[type="file"] {
      padding: 0 gap(m); }
      .fileUploadInput input[type="file"]::-webkit-file-upload-button {
        visibility: hidden;
        margin-left: 10px;
        padding: 0;
        height: 50px;
        width: 0; }
        
  .fileUploadInput button {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 50px;
    height: 50px;
    line-height: 0;
    user-select: none;
    color: white;
    background-color: #323262;
    border-radius: 0 3px 3px 0;
    font-family: arial, sans-serif;
    font-size: 1rem;
    font-weight: 800; }
    .fileUploadInput button svg {
      width: auto;
      height: 50%; }

* {
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
  border: 0px;
  outline: 0;
  background-repeat: no-repeat;
  appearance: none;
  border-radius: 0;
  vertical-align: middle;
  font-weight: inherit;
  font-style: inherit;
  font-family: inherit;
  text-decoration: none;
  list-style: none;
  user-select: text;
  line-height: 1.333em; }

body {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100vh;
  background: rgba(66, 50, 98, 0.05); }

.container {
  padding: 25px;
  box-shadow: 0 0 20px rgba(66, 50, 98, 0.35);
  border: 1px solid #eaeaea;
  border-radius: 3px;
  background: white; }

@-moz-document url-prefix() {
.fileUploadInput button{
    display: none
}
}
<!-- Author: Ali Soueidan-->
<!-- Author URI: https//: www.alisoueidan.com-->

<div class="container">
    <div class="fileUploadInput">
    <label>✨ Upload File</label>
    <input type="file" />
    <button>+</button></div>
</div>


1
这是完美的,到目前为止我见过的最好的。快速问题,有没有办法不显示整个文件名,例如如果文件名太长,它会超过“+”? - Rene Chan
1
@ReneChan 你可以使用CSS将文件名的'overflow'设置为'ellipsis'或'hidden'。 - 7FigureSwagger

5

Bootstrap示例

<label className="btn btn-info btn-lg">
  Upload
  <input type="file" style="display: none" />
</label>

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