样式化input type="file"按钮

1072
如何为按钮添加样式?

<input type="file" />


我会添加我的答案,以展示我是如何做到的...但这里有一个基于Bootstrap的例子,可能会有所帮助。http://geniuscarrier.com/how-to-style-a-html-file-upload-button-in-pure-css/ - Vishnu Narang
这个元素的问题似乎是它不像其他类似的元素那样接受样式。比如 input type="submit">。我将相同的样式应用于两种输入类型,这就是我得到的结果:https://i.imgur.com/7MI1Poh.jpg。 - carloswm85
对我来说有效的方法是在输入元素上方放置一个 div 并将 div 样式设置为所需样式。然后将输入元素的不透明度设置为 0 并将其大小设置为与 div 相同。 - Ricardo Figueiredo
48个回答

26

仅使用CSS

使用这个非常简单易于理解的方式

.choose::-webkit-file-upload-button {
  color: white;
  display: inline-block;
  background: #1CB6E0;
  border: none;
  padding: 7px 15px;
  font-weight: 700;
  border-radius: 3px;
  white-space: nowrap;
  cursor: pointer;
  font-size: 10pt;
}
<label>Attach your screenshort</label>
<input type="file" multiple class="choose">


2
简单但不支持所有地方。 - Owow
1
这比其他解决方案要好得多,因为它显示了所选文件的名称。但是如何更改“选择文件”的文本?一个人真的必须对 HTML/CSS 标准背后的人的能力产生疑问,他们是谁想出这些东西的?做得如此之差。 - Gerry
我只想补充一下,Firefox 有自己类似的类 ::file-selector-button。 - Robert

24
 <label>
    <input type="file" />
 </label>

你可以将type="file"的输入框包裹在一个label标签内。随意设置label的样式,并使用display: none;隐藏输入框。


另一个选择可能是https://gist.github.com/barneycarroll/5244258或http://jsfiddle.net/4cwpLvae/(在IE11中工作)。 - surfmuggle

19

这种方法为你提供了完全的灵活性!ES6 / VanillaJS!

html:

html:

<input type="file" style="display:none;"></input>
<button>Upload file</button>

JavaScript:

document.querySelector('button').addEventListener('click', () => {
  document.querySelector('input[type="file"]').click();
});

这将隐藏输入文件按钮,但在幕后通过另一个正常的按钮点击它,你可以像任何其他按钮一样显然地对其进行样式设置。除了一个无用的DOM节点外,这是唯一没有任何缺点的解决方案。由于使用display:none;,输入按钮不会在DOM中保留任何可见空间。

(我不知道该给谁表扬这个想法。但我从Stackoverflow上的某个地方得到了这个想法。)


15

将上传文件按钮放在您的漂亮按钮或元素上方并将其隐藏。

非常简单,适用于任何浏览器。

<div class="upload-wrap">
    <button type="button" class="nice-button">upload_file</button>
    <input type="file" name="file" class="upload-btn">
</div>

样式

.upload-wrap {
    position: relative;
}

.upload-btn {
    position: absolute;
    left: 0;
    opacity: 0;
}

1
这太棒了,谢谢。谈论最小化的工程实现最佳结果! - Tsar Bomba
不显示所选文件。 - galmok

14
这里有一个解决方案,它并不真正对 <input type="file" /> 元素进行样式设置,而是在其他元素的顶部使用了一个 <input type="file" /> 元素(可以进行样式设置)。由于 <input type="file" /> 元素并不真正可见,因此整体上呈现出一个漂亮的文件上传控件的假象。
我最近遇到了这个问题,尽管 Stack Overflow 上有大量答案,但似乎都不能完全满足我的需求。最终,我对其进行了自定义以获得简单而优雅的解决方案。
我还在 Firefox、IE(11、10 和 9)、Chrome、Opera、iPad 和一些 Android 设备上进行了测试。
以下是 JSFiddle 链接 -> http://jsfiddle.net/umhva747/

$('input[type=file]').change(function(e) {
    $in = $(this);
    $in.next().html($in.val());
    
});

$('.uploadButton').click(function() {
    var fileName = $("#fileUpload").val();
    if (fileName) {
        alert(fileName + " can be uploaded.");
    }
    else {
        alert("Please select a file to upload");
    }
});
body {
    background-color:Black;
}

div.upload {
    background-color:#fff;
    border: 1px solid #ddd;
    border-radius:5px;
    display:inline-block;
    height: 30px;
    padding:3px 40px 3px 3px;
    position:relative;
    width: auto;
}

div.upload:hover {
    opacity:0.95;
}

div.upload input[type="file"] {
    display: input-block;
    width: 100%;
    height: 30px;
    opacity: 0;
    cursor:pointer;
    position:absolute;
    left:0;
}
.uploadButton {
    background-color: #425F9C;
    border: none;
    border-radius: 3px;
    color: #FFF;
    cursor:pointer;
    display: inline-block;
    height: 30px;
    margin-right:15px;
    width: auto;
    padding:0 20px;
    box-sizing: content-box;
}

.fileName {
    font-family: Arial;
    font-size:14px;
}

.upload + .uploadButton {
    height:38px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<form action="" method="post" enctype="multipart/form-data">
    <div class="upload">
        <input type="button" class="uploadButton" value="Browse" />
        <input type="file" name="upload" accept="image/*" id="fileUpload" />
        <span class="fileName">Select file..</span>
    </div>
    <input type="button" class="uploadButton" value="Upload File" />
</form>
希望这有所帮助!!!

2
这是一个巧妙的解决方案,可以应对恶意文件上传样式的恶作剧。 - rmcsharry

13

使用jQuery很容易实现。以下是Ryan建议的代码示例,稍作修改即可。

基本的 HTML:

<div id="image_icon"></div>
<div id="filename"></div>
<input id="the_real_file_input" name="foobar" type="file">

当你准备好时,请确保在输入框上设置样式:opacity: 0。你不能设置display: none,因为它需要可点击性。但是,如果你喜欢的话,可以将其定位在“新建”按钮下方或将其隐藏在其他东西下面,并使用z-index。

设置一些jQuery代码,在点击图像时单击实际的输入框。

$('#image_icon').click(function() {
    $('#the_real_file_input').click();
});

现在你的按钮已经可以使用了。只需在值发生变化时剪切并粘贴即可。

$('input[type=file]').bind('change', function() {
    var str = "";
    str = $(this).val();
    $("#filename").text(str);
}).change();

太好了!你可能需要将val()解析为更有意义的内容,但你应该已经准备好了。


1
这将在FF11中失败 - 原因:由于您无法精确地影响输入字段的大小(仅通过使用html大小),并且按钮(您可以使用css设置高度),如果您的可见输入字段大于原始FF提供的,则会留下一个非常大的盲区 - 用户的观点:在大多数情况下,当单击时,他会抱怨上传不起作用。 - Jeffz
2
不错的想法,但在IE上无法实现。$('#the_real_file_input').click()会触发打开对话框,但文件不会被选入表单,上传将失败。 - Tomas

12

这是一个纯CSS、不需要Javascript或Bootstrap,100%跨浏览器兼容的解决方案!只需复制粘贴一段样式代码,即可测试您的文件上传控件。

与其他帖子所做的那样,此解决方案不会尝试隐藏原始HTML元素并重新创建它。它使用普通的CSS,没有任何花俏技巧或第三方工具,为所有主要浏览器样式化原始文件上传表单控件。您甚至不需要更改HTML代码!只需将以下代码复制粘贴到您的网页中进行测试即可...

<style>
/* Note: This CSS will style all instances of 
   <input type=file /> controls in your website. */
input[type="file"],
input[type="file"]:visited,
input[type="file"]:hover,
input[type="file"]:focus,
input[type="file"]:active {
    margin:0;
    padding: 0em 0em;/* fallback: older browsers like IE 1-8 need "em" */
    padding: 0rem 0rem;/* older browsers dont know what "rem" is */
    overflow: hidden; /* long file names overflow so just hide the end */
    background: #fff;
    border-radius: .2em;
    border-radius: .2rem;
    outline: none;
    border: 2px solid #bbb;
    cursor: pointer;
    -webkit-appearance: textfield;
    -moz-appearance: textfield;
}

input[type="file"]:hover {
    background: #f9f9ff; /* Optional rollover color: I am using a light blue to indicate an interaction */
    border: 2px solid #999;
}

input[type="file"]:visited,
input[type="file"]:focus,
input[type="file"]:active {
    background: #fff; /* Default back to white when focused. */
    border: 2px solid #999;
}

/* Note: These "disabled" selectors blow up in IE so have to be separated from the same styles above. */
input[type="file"]:disabled {
    margin: 0;
    padding: 0em 0em;
    padding: 0rem 0rem;
    overflow: hidden; /* long file names overflow so just hide the end */
    background: #ddd;
    border-radius: .2em;
    border-radius: .2rem;
    outline: none;
    border: 2px solid #bbb;
    cursor: pointer;
    -webkit-appearance: textfield;
    -moz-appearance: textfield;
}

input[type="file"]:disabled:hover {
    background: #ddd; /* disabled-readonly buttons should be grey */
    border: 2px solid #999;
}

input[type="file"]:disabled:visited,
input[type="file"]:disabled:focus,
input[type="file"]:disabled:active {
    background: #ddd; /* disabled-readonly buttons should be grey */
    border: 2px solid #999;
}

/* IE UPLOAD BUTTON STYLE: This attempts to alter the file upload button style in IE.  Keep in mind IE gives you limited design control but at least you can customize its upload button.*/
::-ms-browse { /* IE */
    display: inline-block;
    margin: 0;
    padding: .2em .5em;
    padding: .2rem .5rem;
    text-align: center;
    outline: none;
    border: none;
    background: #fff;
    white-space: nowrap;
    cursor: pointer;
}
/* FIREFOX UPLOAD BUTTON STYLE */
::file-selector-button {/* firefox */
    display: inline-block;
    margin: 0rem 1rem 0rem 0rem;
    padding: .18em .5em;
    padding: .18rem .5rem;
    -webkit-appearance: button;
    text-align: center;
    border-radius: .1rem 0rem 0rem .1rem;
    outline: none;
    border: none;
    border-right: 2px solid #bbb;
    background: #eee;
    white-space: nowrap;
    cursor: pointer;
}
/* CHROME AND EDGE UPLOAD BUTTON STYLE */
::-webkit-file-upload-button { /* chrome and edge */
    display: inline-block;
    margin: 0rem 1rem 0rem 0rem;
    padding: .19em .5em;
    padding: .19rem .5rem;
    -webkit-appearance: button;
    text-align: center;
    border-radius: .1rem 0rem 0rem .1rem;
    outline: none;
    border: none;
    border-right: 2px solid #bbb;
    background: #eee;
    white-space: nowrap;
    cursor: pointer;
}
</style>

<input type="file" id="fileupload" name="fileupload" 
value="" tabindex="0" enctype="multipart/form-data" 
accept="image/*" autocomplete="off" multiple="multiple" 
aria-multiselectable="true" title="Multiple File Upload" 
aria-label="Multiple File Upload" />

<br /><br />

<input disabled="disabled" type="file" id="fileupload" 
name="fileupload" value="" tabindex="0" 
enctype="multipart/form-data" accept="image/*" 
autocomplete="off" multiple="multiple" 
aria-multiselectable="true" title="Disabled Multiple File Upload" 
aria-label="Disabled Multiple File Upload" />

以下是 Firefox、Chrome 和 Edge 中使用下面的 CSS 控制文件上传控件的外观。这是一个非常简单干净的设计。您可以将其更改为任何您喜欢的样子:

enter image description here

Internet Explorer仅提供有限的设计控制,但至少您可以使用CSS操纵控件,以更改一些内容,包括圆角边框和颜色:

enter image description here

我的解决方案优点有:

  1. 您可以使用简单的CSS来设置原始HTML输入控件的样式
  2. 您可以在文件输入文本框中看到一个或多个文件名
  3. 屏幕阅读器和ARIA友好设备可以正常与您的文件上传控件交互
  4. 您可以在HTML元素上设置tabindex,使其成为选项卡顺序的一部分
  5. 因为您使用的是纯HTML和CSS,所以您的文件输入按钮在旧版和新版浏览器中都可以完美地工作
  6. 不需要任何JavaScript!
  7. 在即使是最老的浏览器中也能运行和加载得非常快
  8. 因为您没有使用“display:none”来隐藏控件,所以其文件块流数据在任何已知的旧版或新版浏览器中都不会被禁用以达到服务器

您不需要使用愚蠢的JavaScript技巧、Bootstrap或尝试隐藏/重新创建文件输入控件。那只会破坏每个在线用户的可用性。样式化原始HTML控件意味着您的文件上传控件保证在 25 年的 Web 浏览器中工作良好,无论是旧版还是新版。

这就是为什么您不能信任所有这些在此处擦除、重写或破坏 HTML 的“脚本黑客”来尝试重新创建某些视觉体验。这表明您不理解 HTML 的使用方式或它为什么几乎未经改变地存在了 30 年。您永远不应该尝试重写 HTML 的本机表单控件功能。为什么?使用自然 HTML 在网站中还涉及到更多东西,而不仅仅是操纵标记以实现某种强制视觉体验。这些替换 HTML 元素的有限视觉设计的权衡是有原因的。

我的建议:坚持使用简单的 HTML 和 CSS 解决方案,您将成为一个零问题的 Web 开发人员。


1
这才是真正的解决方案!非常感谢!(对于其他人:按钮文本无法直接更改或在输入元素上使用:after和:before,它需要一个带有“pointer-events:none;”的单独元素放置在按钮顶部。) - Barney Szabolcs
这需要针对暗模式进行调整。所有的背景都设置为白色。除此之外,它很好,只需要一点ctrl+h。 - Patafikss
@Patafikss 是的,说得好。我的解决方案更像是应用于所有浏览器(旧版和新版)的默认重置表格。如果您想要一个深色模式版本,我会设置“prefers-color-scheme”媒体查询与深色版本,并不仅样式化我的输入,而且还有所有表单字段的深色版本。 - Stokely

8

可见性隐藏技巧

我通常使用visibility:hidden技巧

这是我的样式化按钮

<div id="uploadbutton" class="btn btn-success btn-block">Upload</div>

这是一个文件上传按钮,注意要使用visibility:hidden规则隐藏它。
<input type="file" id="upload" style="visibility:hidden;">

这是将它们连接在一起的 JavaScript 代码。它有效地实现了连接。

<script>
 $('#uploadbutton').click(function(){
    $('input[type=file]').click();
 });
 </script>

1
你不能使用click()方法来触发文件输入类型的事件。出于安全原因,大多数浏览器都不允许这样做。 - Mahi
使用jQuery甚至可以吗?这样做正确吗?你会用什么方法代替它? - Gianluca Ghettini
https://dev59.com/d3VC5IYBdhLWcg3wsTbv - Mahi
style="visibility:hidden" is too long, simply use hidden. Also, click() does work for any browsers and there is no veryfiable security reason as of now and on any devices it's the legit way and @Gianluca for classic jQuery use trigger() - Thielicious
1
这正是我要添加的解决方案!它可以工作,并且您可以按照自己的意愿精确地显示它。适用于Chrome,将尝试其他浏览器。 - markthewizard1234

8
<input type="file" name="media" style="display-none" onchange="document.media.submit()">

我通常会使用简单的JavaScript来自定义文件输入标签。在按钮点击时调用隐藏的输入字段,这是一个简单的解决方案,没有任何CSS或大量的jQuery。

<button id="file" onclick="$('#file').click()">Upload File</button>

1
你不能使用 click() 方法来触发文件输入类型的事件。出于安全原因,大多数浏览器都不允许这样做。 - Mahi

8

转换文件名的多文件解决方案

Bootstrap 示例

HTML:

<div>
  <label class="btn btn-primary search-file-btn">
    <input name="file1" type="file" style="display:None;"> <span>Choose file</span>
  </label>
  <span>No file selected</span>
</div>

<div>
  <label class="btn btn-primary search-file-btn">
    <input name="file2" type="file" style="display:None;"> <span>Choose file</span>
  </label>
  <span>No file selected</span>
</div>

1. 使用jQuery的JS:

$().ready(function($){
    $('.search-file-btn').children("input").bind('change', function() {
    var fileName = '';
    fileName = $(this).val().split("\\").slice(-1)[0];
    $(this).parent().next("span").html(fileName);
  })
});

2. 不使用jQuery的JS

Array.prototype.forEach.call(document.getElementsByTagName('input'), function(item) {
  item.addEventListener("change", function() {
    var fileName = '';
    fileName = this.value.split("\\").slice(-1)[0];
    this.parentNode.nextElementSibling.innerHTML = fileName;
  });
});

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