Cross-browser custom styling for file upload button

我试图设计一个文件上传按钮到我的个人喜好,但我不能找到任何真正可靠的方式来做到这一点没有 JS。我确实找到了关于这个主题的 其他问题,但是那里的答案要么涉及到 JavaScript,要么建议使用 夸克斯莫德的方法

My major issue with this Quirksmode's approach is that the file button will still have the browser-defined dimensions, so it won't automatically adjust to whatever's used as button that's placed below it. I've made some code, based on it, but it will just take up the space the file button would normally take up, so it won't at all fill the parent div like I want it to.

HTML:

<div class="myLabel">
<input type="file"/>
<span>My Label</span>
</div>

CSS:

.myLabel {
position: relative;
}
.myLabel input {
position: absolute;
z-index: 2;
opacity: 0;
width: 100%;
height: 100%;
}

这个小提琴 演示了这种方法是如何存在缺陷的。在 Chrome 中,单击第二个演示按钮下面的 !!将打开文件对话框,但在其他所有浏览器中,文件按钮不会占用该按钮的正确区域。

有没有更好的方法来设计文件上传按钮,不使用任何 JavaScript,最好使用尽可能少的“ hacky”代码(因为黑客通常会带来其他问题,比如小提琴中的问题) ?

175218 次浏览

I'm posting this because (to my surprise) there was no other place I could find that recommended this.

有一个非常简单的方法可以做到这一点,而不需要限制您使用浏览器定义的输入维度。只需使用 <label>标签周围的隐藏文件上传按钮。这允许甚至更多的自由样式比样式允许通过 Webkit 的内置样式[1]

Label 标签的确切目的是将任何 click 事件导向它的子 inputs[2],因此使用它,您不再需要任何 JavaScript 将 click 事件导向输入按钮。你应该使用下面这样的东西:

label.myLabel input[type="file"] {
position:absolute;
top: -1000px;
}


/***** Example custom styling *****/
.myLabel {
border: 2px solid #AAA;
border-radius: 4px;
padding: 2px 5px;
margin: 2px;
background: #DDD;
display: inline-block;
}
.myLabel:hover {
background: #CCC;
}
.myLabel:active {
background: #CCF;
}
.myLabel :invalid + span {
color: #A44;
}
.myLabel :valid + span {
color: #4A4;
}
<label class="myLabel">
<input type="file" required/>
<span>My Label</span>
</label>

我使用了一个固定的位置来隐藏输入,这样即使在古老版本的 Internet Explorer 中也能正常工作(模拟 IE8-拒绝在 visibility:hidden或者 display:none文件输入中工作)。我已经在模拟 IE7及以上版本中进行了测试,它运行得非常完美。


  1. You can't use <button>s inside <label> tags unfortunately, so you'll have to define the styles for the buttons yourself. To me, this is the only downside to this approach.
  2. 如果定义了 for属性,则使用其值触发输入,其 id<label>上的 for属性相同。

这似乎把生意照顾得很好

超文本标示语言

<label for="upload-file">A proper input label</label>


<div class="upload-button">


<div class="upload-cover">
Upload text or whatevers
</div>


<!-- this is later in the source so it'll be "on top" -->
<input name="upload-file" type="file" />


</div> <!-- .upload-button -->

CSS

/* first things first - get your box-model straight*/
*, *:before, *:after {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}


label {
/* just positioning */
float: left;
margin-bottom: .5em;
}


.upload-button {
/* key */
position: relative;
overflow: hidden;


/* just positioning */
float: left;
clear: left;
}


.upload-cover {
/* basically just style this however you want - the overlaying file upload should spread out and fill whatever you turn this into */
background-color: gray;
text-align: center;
padding: .5em 1em;
border-radius: 2em;
border: 5px solid rgba(0,0,0,.1);


cursor: pointer;
}


.upload-button input[type="file"] {
display: block;
position: absolute;
top: 0; left: 0;
margin-left: -75px; /* gets that button with no-pointer-cursor off to the left and out of the way */
width: 200%; /* over compensates for the above - I would use calc or sass math if not here*/
height: 100%;
opacity: .2; /* left this here so you could see. Make it 0 */
cursor: pointer;
border: 1px solid red;
}


.upload-button:hover .upload-cover {
background-color: #f06;
}

最好的例子是这一个,没有隐藏,没有 jQuery,它是完全纯 CSS

Http://css-tricks.com/snippets/css/custom-file-input-styling-webkitblink/

.custom-file-input::-webkit-file-upload-button {
visibility: hidden;
}


.custom-file-input::before {
content: 'Select some files';
display: inline-block;
background: -webkit-linear-gradient(top, #f9f9f9, #e3e3e3);
border: 1px solid #999;
border-radius: 3px;
padding: 5px 8px;
outline: none;
white-space: nowrap;
-webkit-user-select: none;
cursor: pointer;
text-shadow: 1px 1px #fff;
font-weight: 700;
font-size: 10pt;
}


.custom-file-input:hover::before {
border-color: black;
}


.custom-file-input:active::before {
background: -webkit-linear-gradient(top, #e3e3e3, #f9f9f9);
}
<input type="file" class="custom-file-input">

请在下面找到一种适用于所有浏览器的方法。基本上我把输入放在图像的顶部。 我使它巨大的使用字体大小,所以用户总是点击上传按钮。

.myFile {
position: relative;
overflow: hidden;
float: left;
clear: left;
}
.myFile input[type="file"] {
display: block;
position: absolute;
top: 0;
right: 0;
opacity: 0;
font-size: 100px;
filter: alpha(opacity=0);
cursor: pointer;
}
<label class="myFile">
<img src="http://wscont1.apps.microsoft.com/winstore/1x/c37a9d99-6698-4339-acf3-c01daa75fb65/Icon.13385.png" alt="" />
<input type="file" />
</label>

I just came across this problem and have written a solution for those of you who are using Angular. You can write a custom directive composed of a container, a button, and an input element with type file. With CSS you then place the input over the custom button but with opacity 0. You set the containers height and width to exactly the offset width and height of the button and the input's height and width to 100% of the container.

指令

angular.module('myCoolApp')
.directive('fileButton', function () {
return {
templateUrl: 'components/directives/fileButton/fileButton.html',
restrict: 'E',
link: function (scope, element, attributes) {


var container = angular.element('.file-upload-container');
var button = angular.element('.file-upload-button');


container.css({
position: 'relative',
overflow: 'hidden',
width: button.offsetWidth,
height: button.offsetHeight
})


}


};
});

如果你使用的是翡翠,你可以使用翡翠模板

div(class="file-upload-container")
button(class="file-upload-button") +
input#file-upload(class="file-upload-input", type='file', onchange="doSomethingWhenFileIsSelected()")

如果使用 html,则在 html 中使用相同的模板

<div class="file-upload-container">
<button class="file-upload-button"></button>
<input class="file-upload-input" id="file-upload" type="file" onchange="doSomethingWhenFileIsSelected()" />
</div>

CSS

.file-upload-button {
margin-top: 40px;
padding: 30px;
border: 1px solid black;
height: 100px;
width: 100px;
background: transparent;
font-size: 66px;
padding-top: 0px;
border-radius: 5px;
border: 2px solid rgb(255, 228, 0);
color: rgb(255, 228, 0);
}


.file-upload-input {
position: absolute;
top: 0;
left: 0;
z-index: 2;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}

任何覆盖所有文件输入的简单方法就是设置你的输入[ type = Button ]的样式,然后把它放在全局范围内,把文件输入转换成按钮:

$(document).ready(function() {
$("input[type=file]").each(function () {
var thisInput$ = $(this);
var newElement = $("<input type='button' value='Choose File' />");
newElement.click(function() {
thisInput$.click();
});
thisInput$.after(newElement);
thisInput$.hide();
});
});

下面是我从 http://cssdeck.com/labs/beautiful-flat-buttons得到的一些 CSS 样例按钮:

input[type=button] {
position: relative;
vertical-align: top;
width: 100%;
height: 60px;
padding: 0;
font-size: 22px;
color:white;
text-align: center;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
background: #454545;
border: 0;
border-bottom: 2px solid #2f2e2e;
cursor: pointer;
-webkit-box-shadow: inset 0 -2px #2f2e2e;
box-shadow: inset 0 -2px #2f2e2e;
}
input[type=button]:active {
top: 1px;
outline: none;
-webkit-box-shadow: none;
box-shadow: none;
}

如果你使用 Bootstrap 和 LESS,也很容易设计标签:

label {
.btn();
.btn-primary();


> input[type="file"] {
display: none;
}
}