样式化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个回答

3
我发现最好的方法是将设置为display:none并给它一个id。创建一个按钮或其他元素来打开文件输入。然后在该按钮(button)上添加事件侦听器,当单击该按钮时,模拟单击原始文件输入。就像单击名为“hello”的按钮,但它打开了一个文件窗口。
示例代码:
//i am using semantic ui

<button class="ui circular icon button purple send-button" id="send-btn">
      <i class="paper plane icon"></i>
    </button>
  <input type="file" id="file" class="input-file" />

JavaScript

var attachButton=document.querySelector('.attach-button');
    attachButton.addEventListener('click', e=>{
        $('#file').trigger("click")
    })

2

最好的方法是使用伪元素 :after 或 :before 作为覆盖输入框的元素。然后按照您的要求对该伪元素进行样式设置。我建议您为所有输入框都采用以下通用样式:

input {
  height: 0px;
  outline: none;
}

input[type="file"]:before {
  content: "Browse";
  background: #fff;
  width: 100%;
  height: 35px;
  display: block;
  text-align: left;
  position: relative;
  margin: 0;
  margin: 0 5px;
  left: -6px;
  border: 1px solid #e0e0e0;
  top: -1px;
  line-height: 35px;
  color: #b6b6b6;
  padding-left: 5px;
  display: block;
}

2

使用一些技巧,CSS可以在这里发挥很大的作用...

<div id='wrapper'>
    <input type='file' id='browse'>
</div>
<style>
    #wrapper {
            width: 93px; /*play with this value */
            height: 28px; /*play with this value */
            background: url('browseBtn.png') 0 0 no-repeat;
            border:none;
            overflow:hidden;
    }

    #browse{
            margin-left:-145px; /*play with this value */
            opacity:0; /* set to .5 or something so you can better position it as an overlay then back to zero again after you're done */
            -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
            filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);
    }
</style>

::reference::http://site-o-matic.net/?viewpost=19

-abbey


2

正如JGuoCorySimmons所提到的,您可以利用可样式化标签的可点击行为,隐藏不太灵活的文件输入元素。

<!DOCTYPE html>
<html>
<head>
<title>Custom file input</title>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
</head>

<body>

<label for="upload-file" class="btn btn-info"> Choose file... </label>
<input id="upload-file" type="file" style="display: none"
onchange="this.nextElementSibling.textContent = this.previousElementSibling.title = this.files[0].name">
<div></div>

</body>
</html>

2
一个适用于大多数后端的图像上传应用程序演示,具有漂亮的动画特效。

// common
function render_element(styles, el) {
    for (const [kk, vv] of Object.entries(styles)) {
        el.style[kk] = vv;
    }
}

function hoverOpacity(el) {
    el.addEventListener('mouseenter', function() {
        el.style.opacity = 0.75
    }.bind(el));
    el.addEventListener('mouseleave', function() {
        el.style.opacity = 1
    }.bind(el));
}

// return void event handler on setTimeout
function buffer(func, time){
    return e=>{
        if(func.still)return;
        // first runtime
        if(!func.pft){
            func(e);
            func.pft = true;
            func.still = false;
            return;
        }
        func.still = true;
        setTimeout(e=>{
            func(e);
            func.still = false;
        }, time);
    }
}
// end of common

const imageUploadButton = document.getElementById('image-upload-button');
imageUploadButton.addEventListener('click', e=>{
    // pulse animation total time
    const d1 = document.getElementById('image-form');
    let time = 600;

    if(d1.rendered){
        d1.ready();
    }else{
        d1.ready = function(){
            d1.style.display = 'flex';
            d1.style.background = '#c5edd0';
            this.d2.style.background = '#b4dbbf';
            this.d3.style.background = '#95dea9';
            this.d4.innerHTML = 'Drag and Drop or Click Above to Upload';
        }
        let dismiss_btn = document.createElement('div');
        render_element({
            position: 'absolute',
            height: '30px',
            width: '30px',
            top: '0', 
            right: '0',
            background: '#fff',
            borderRadius: '30px',
            cursor: 'pointer', 
            margin: '2px',
            zIndex: '10',
        }, dismiss_btn);
        dismiss_btn.addEventListener('mouseenter', function(){this.style.background = '#fc4f30'});
        dismiss_btn.addEventListener('mouseleave', function(){this.style.background = '#fff'});
        dismiss_btn.addEventListener('click', ()=>{d1.style.display = 'none'});
        d1.appendChild(dismiss_btn);
        const d3 = d1.querySelector('#image-input');
        const d5 = d1.querySelector('#image-submit');
        d5.style.visibility = 'hidden';
        d1.parentNode.removeChild(d1);
        document.body.appendChild(d1);
        d1.removeChild(d3);
        let [
            d2, 
            d4, 
        ] = Array.from({length: 3}, ()=>document.createElement('div'));
        let width = window.innerWidth;
        let d_styles = {
            display: 'flex',
            justifyContent: 'center', 
            alignItems: 'center',
        };
        render_element({
            position: 'fixed',
            left: ((width - 430) / 2).toString() + 'px', 
            width: '430px',
            top: '60px',
            height: '280px',
            zIndex: '10', 
        }, d1);
        render_element(d_styles, d1);

        render_element({
            width: '90%',
            height: '90%', 
        }, d2);
        render_element(d_styles, d2);

        render_element({
            width: '80%',
            height: '70%', 
            fontSize: '0',
            cursor: 'pointer',
        }, d3);
        hoverOpacity(d3);
        render_element(d_styles, d3);

        d1.appendChild(d2);
        d2.appendChild(d3);

        let tt = time / 3;
        let ht = tt / 2;
        d1.addEventListener('dragover', buffer(e=>{
            d1.style.background = '#ebf9f0';
            setTimeout(()=>{
                d1.style.background = '#95dea9';
            }, ht);
            setTimeout(()=>{
                d2.style.background = '#b6e3c2';
                setTimeout(()=>{
                    d2.style.background = '#c4eed2';
                }, ht);
            }, tt);
            setTimeout(()=>{
                d3.style.background = '#cae3d1';
                setTimeout(()=>{
                    d3.style.background = '#9ce2b4';
                }, ht);
            }, tt);
        }, time));

        d2.style.flexDirection = 'column';
        render_element({
            fontSize: '16px',
            textAlign: 'center',
            fontFamily: 'Verdana',
        }, d4);
        d2.appendChild(d4);

        d3.addEventListener('change', e=>{
            // backend
            // d5.click();
            // if backend succeed, run frontend
            setTimeout(()=>{
                d1.style.background = '#dbcea2';
                setTimeout(()=>{
                    d2.style.background = '#dbc169';
                    setTimeout(()=>{
                        d3.style.background = '#ebc034';
                    }, ht);
                }, tt);
            }, time);
            // display backend path here
            // now only display filename
            d4.innerHTML = d3.files[0].name;
        });
        d1.d2 = d2;
        d1.d3 = d3;
        d1.d4 = d4;
        d1.ready();
        d1.rendered = true;
    }
});
#image-upload-button{
    width: 200px;
    height: 40px;
    background: lightgrey;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

#image-form{
    display: none;
}

::-webkit-file-upload-button {
    visibility: hidden;
}
<div id="image-upload-button">Upload Image
    <form id="image-form" action="post">
        <input id="image-input" type="file" />
        <button id="image-submit" type="submit"></button>
    </form>
</div>


1
如果你正在寻找一个开箱即用的JavaScript库,jquery-fileinput 是一个不错的选择。

1
您可以将一个非常棒(未完成的)文件上传器转换为 <button> 元素或任何其他元素:

function selectFile() {
    document.getElementById("fileSelector").click();
}
input#fileSelector[type="file"] {
    display: none;
}

button[onclick*="()"] {
    cursor: pointer;
}
<input type="file" id="fileSelector">
<button onclick="selectFile()">Select file from computer...</button>


1

这里有很多解决方案,但我想加入一些现代考虑因素。没有隐藏或可见性的黑客技巧。仍需要JS来增强反馈和拖放功能。

关键在于将按钮设置为100%宽度;

[type="file"]::file-selector-button {
  width: 100%;
}

[type="file"] {
  width: 50%;
  min-width: 14ch;
}

[type="file"]::file-selector-button {
  width: 100%;
  margin-inline-end: 0;
  padding: 0.6rem;
  background-color: lightblue;
  color: smoke;
  border: none;
  border-radius: 0;
  text-transform: uppercase;
}
<input type="file" />


1

这里有一个仅使用css的简单解决方案,创建了一个一致的目标区域,并让您可以自由地样式化假元素。

基本思路是:

  1. 在真正的文件输入框旁边添加两个“伪”元素(文本输入/链接)。将它们绝对定位,使它们恰好在目标区域上方。
  2. 用div包装您的文件输入框。将溢出设置为隐藏(以便文件输入框不会溢出),并将其大小设置为您想要的目标区域大小。
  3. 将文件输入框的不透明度设置为0,以使其隐藏但仍可点击。将其字体大小设置得很大,以便您可以点击目标区域的所有部分。

这是jsfiddle: http://jsfiddle.net/gwwar/nFLKU/

<form>
    <input id="faux" type="text" placeholder="Upload a file from your computer" />
    <a href="#" id="browse">Browse </a>
    <div id="wrapper">
        <input id="input" size="100" type="file" />
    </div>
</form>

嗨 Kerry,你的代码可以很好地为按钮设置样式,但是当我们选择文件时,占位符也应该被更改。请问你能否帮忙解决这个问题?在选择文件后更改占位符是否可行? - Khushbu Vaghela

1
这些答案都很不错,但它们只适用于非常具体的情况。也就是说,它们是有偏见的。
所以,这里有一个答案,假定什么都不知道,但无论如何修改,都可以使用。您可以通过css更改设计,添加javascript来显示更改后的文件名称等等,它仍将始终工作。
代码:
这是核心CSS。
.file-input{
  pointer-events: none;
  position: relative;
  overflow: hidden;
}
.file-input > * {
  pointer-events: none;
}
.file-input > input[type="file"]{
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  opacity: 0;
  pointer-events: all;
  cursor: pointer;
  height: 100%;
  width: 100%;
}

and the core html:

<div class="file-input">
  <input type="file"/>
</div>

正如您所看到的,我们正在强制将发生在 .file-input 元素或其任何子元素上的任何指针事件(点击)代理到文件输入中。这是因为文件输入被定位为绝对位置,并且始终会占用容器的宽度/高度。因此,您可以自定义以适应您的需求。将包装器样式化为按钮,使用一些js在选择时显示文件名等。只要上述核心代码保持不变,就不会出现任何问题。

正如您在演示中所看到的,我已经添加了一个带有文本“选择文件”的 span 和一个带有额外样式的类来样式化 .file-input div。这应该是任何想要创建自定义文件上传元素的人的规范起点。

演示:JSFIDDLE


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