Html 文件上传按钮的跨浏览器自定义样式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21842274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 00:57:22  来源:igfitidea点击:

Cross-browser custom styling for file upload button

htmlcsscross-browserfile-io

提问by Joeytje50

I'm trying to style a file upload button to my personal preferences, but I couldn't find any really solid ways to do this without JS. I did find twootherquestions about this subject, but the answers there either involved JavaScript, or suggested Quirksmode's approach.

我正在尝试根据我的个人偏好设置文件上传按钮的样式,但是如果没有 JS,我找不到任何真正可靠的方法来做到这一点。我确实找到关于这个主题的另外两个问题,但那里的答案要么涉及 JavaScript,要么建议Quirksmode 的方法

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.

我对这种 Quirksmode 方法的主要问题是文件按钮仍将具有浏览器定义的尺寸,因此它不会自动调整到用作放置在其下方的按钮的任何内容。我已经基于它编写了一些代码,但它只会占用文件按钮通常占用的空间,因此它根本不会像我想要的那样填充父 div。

HTML:

HTML:

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

CSS:

CSS:

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

This fiddledemonstrates how this approach is quite flawed. In Chrome, clicking the !!below the second demo button will open the file dialog anyway, but also in all other browsers, the file button doesn't take up the correct areas of the button.

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

Is there any more solid way to style the file upload button, without any JavaScript, and preferably using as little 'hacky' coding as possible (since hacking usually brings other problems along with it, such as the ones in the fiddle)?

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

回答by Joeytje50

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

我发布这个是因为(令我惊讶)我找不到其他推荐这个的地方。

There's a really easy way to do this, without restricting you to browser-defined input dimensions. Just use the <label>tag around a hidden file upload button. This allows for even more freedom in styling than the styling allowed via webkit's built-in styling[1].

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

The label tag was made for the exact purpose of directing any click events on it to the child inputs[2], so using that, you won't require any JavaScript to direct the click event to the input button for you anymore. You'd to use something like the following:

label 标签的确切目的是将其上的任何点击事件定向到子输入[2],因此使用它,您将不再需要任何 JavaScript 将点击事件定向到输入按钮。您将使用以下内容:

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>

I've used a fixed position to hide the input, to make it work even in ancient versions of Internet Explorer (emulated IE8- refused to work on a visibility:hiddenor display:nonefile-input). I've tested in emulated IE7 and up, and it worked perfectly.

我使用了一个固定位置来隐藏输入,以使其即使在古老版本的 Internet Explorer 中也能工作(模拟 IE8-拒绝在输入visibility:hiddendisplay: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. If the forattribute is defined, its value is used to trigger the input with the same idas the forattribute on the <label>.
  1. 不幸的是,您不能<button><label>标签内使用s ,因此您必须自己定义按钮的样式。对我来说,这是这种方法的唯一缺点。
  2. 如果for定义了属性,则使用其值来触发与 上idfor属性相同的输入<label>

回答by regisbsb

Please find below a way that works on all browsers. Basically I put the input on top the image. I make it huge using font-size so the user is always clicking the upload button.

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

.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>

回答by Shamal Sandeep

The best example is this one, No hiding, No jQuery, It's completely pure CSS

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

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

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">

回答by sheriffderek

This seems to take care of business pretty well. A fidde is here:

这似乎很好地照顾了业务。一个 fidde 在这里:

HTML

HTML

<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

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;
}

回答by Cymricus

Any easy way to cover ALL file inputs is to just style your input[type=button] and drop this in globally to turn file inputs into buttons:

覆盖所有文件输入的任何简单方法就是设置 input[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();
    });
});

Here's some sample button CSS that I got from http://cssdeck.com/labs/beautiful-flat-buttons:

这是我从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;
}

回答by Benjamin Conant

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 的人编写了一个解决方案。您可以编写由容器、按钮和类型为文件的输入元素组成的自定义指令。然后使用 CSS 将输入放在自定义按钮上,但不透明度为 0。将容器的高度和宽度设置为按钮的偏移宽度和高度,将输入的高度和宽度设置为容器的 100%。

the directive

指令

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
        })

      }

    };
  });

a jade template if you are using jade

如果您使用的是玉石,则为玉石模板

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

the same template in html if you are using html

如果您使用的是 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>

the css

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;
}

回答by sdvnksv

It's also easy to style the label if you are working with Bootstrap and LESS:

如果您使用 Bootstrap 和 LESS,也可以轻松设置标签样式:

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

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