如何使用CSS3 / Javascript为“input file”添加样式?

37
我希望使用CSS3来样式化。另外,我想让用户点击一个我将样式化的
,这将打开浏览器窗口。是否可以仅使用HTML、CSS3和JavaScript / jQuery来实现?

1
当然可以,但我还没有找到足够好的解决方案。 - Misha Moroshko
检查这个很棒的技巧:http://stackoverflow.com/q/6638434/809356 - Sophivorus
2
只需使用这种方法。 这确实是最简单的方法,在所有浏览器中都可以完美运行,而且根本不需要任何JavaScript。 - Joeytje50
如果您不想直接处理此处描述的与样式相关的技巧,且可以使用Polymer/web组件,并且不需要支持IE9或更早版本,请查看我创建的自定义元素: https://github.com/garstasio/file-input。它还提供了许多其他功能,使文件输入更加便捷。 - Ray Nicholus
12个回答

53

我有一个简略的例子,你可能想要得到一些想法...

HTML

<div id="file">Chose file</div>
<input type="file" name="file" />​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

CSS

#file {
    display:none;
}​

jQuery

var wrapper = $('<div/>').css({height:0,width:0,'overflow':'hidden'});
var fileInput = $(':file').wrap(wrapper);

fileInput.change(function(){
    $this = $(this);
    $('#file').text($this.val());
})

$('#file').click(function(){
    fileInput.click();
}).show();

演示

‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã‚Äã


3
在IE中,当您点击提交按钮时,这将清空所选文件并取消提交(安全特性?),因为用户实际上没有在文件输入框上进行单击操作,有没有办法解决这个问题?但在FF4中可以正常工作。 - invertedSpear
1
对于多个文件,同样的想法。仅在ff上测试过。http://jsfiddle.net/2ezhd/ - fotanus
1
@Juan "大概的例子"… - Reigel Gallarde
你可以通过仅使用CSS3来以最快的方式实现相同的效果。看看我的Pen: http://codepen.io/Despertaweb/pen/MawOyO - Despertaweb
1
@Reigel,你是对的,我以为很久之前就检查过了...谢谢! - Despertaweb
显示剩余7条评论

19

在查看了Reigel的想法和这篇文章后,我写了这个简单的解决方案来解决样式化type="file"输入字段的常见问题(在Firefox、Safari和Chrome上测试过)。

<div style="position:relative;">
<div id="file" style="position:absolute;">Click here to select a file</div>
<input type="file" name="file" style="opacity:0; z-index:1;" onchange="document.getElementById('file').innerHTML = this.value;">
</div>

然后你当然可以按照自己的喜好样式化“file”div。

如果你想使用type="text"输入框而不是一个div,只需将innerHTML更改为value

<div style="position:relative;">
<input type="text" id="file" style="position:absolute;" placeholder="Click here to select a file">
<input type="file" name="file" style="opacity:0; z-index:1;" onchange="document.getElementById('file').value = this.value;">
</div>

以下是使用jQuery的原始答案:

<div style="position:relative;">
<div id="file" style="position:absolute;">Click here to select a file</div>
<input type="file" name="file" style="opacity:0; z-index:1;" onchange="$('#file').text($(this).val());">
</div>

1
这种技术的缺点是文件输入仍然呈现为可点击目标(你看不见)。如果你将“file” div样式设置得比隐藏的<input type='file'>小,那么你就留下了透明的点击目标,围绕它或其他表单元素。只要你将div样式设置得比任何浏览器原生文件元素都大,它就可以正常工作。 - user85461
将文件选择元素的宽度和高度设置为其父容器区域的100%,并且无论浏览器如何呈现本机GUI元素,它都应该被适当地调整大小。至少,在最新的FF,Chrome,Safari和IE9/10中,这对我有效。 - jerseyboy

6
这是使用HTML、CSS和Javascript(无需任何框架)完成的方法:
隐藏按钮,并使用一个假的
作为文件上传按钮。在单击此
时,我们调用隐藏的
演示:
// comments inline

document.getElementById("customButton").addEventListener("click", function(){
  document.getElementById("fileUpload").click();  // trigger the click of actual file upload button
});

document.getElementById("fileUpload").addEventListener("change", function(){
  var fullPath = document.getElementById('fileUpload').value;
  var fileName = fullPath.split(/(\\|\/)/g).pop();  // fetch the file name
  document.getElementById("fileName").innerHTML = fileName;  // display the file name
}, false);
body{
  font-family: Arial;
}

#fileUpload{
  display: none; /* do not display the actual file upload button */
}

#customButton{  /* style the dummy upload button */
  background: yellow;
  border: 1px solid red;
  border-radius: 5px;
  padding: 5px;
  display: inline-block;
  cursor: pointer;
  color: red;
}
<input type="file" id="fileUpload"> <!-- actual file upload button -->
<div id="customButton">Browse</div>  <!-- dummy file upload button which can be used for styling ;) -->
<span id="fileName"></span> <!-- the file name of the selected file will be shown here -->


1
真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒,真棒。 - Rasmus

6

我还为此制作了自定义样式,请查看

JS Fiddle演示 - 自定义输入类型="file"

HTML

<input type="file" id="test">
<div class="button-group"> 
<a href="#" id="browse" class="button primary">Browse</a>
<a href="#" id="save" class="button">Save</a>
<a href="#" id="clear" class="button danger">Clear</a>
</div>
<input type="text" id="testfile"></input>

CSS

body {
padding:100px;
}
input[type="file"] {
position:absolute;
display:none;
}
#testfile {
height: 26px;
text-decoration: none;
background-color: #eee;
border:1px solid #ccc;
border-radius:3px;
float:left;
margin-right:5px;
overflow:hidden;
text-overflow:ellipsis;
color:#aaa;
text-indent:5px;
}
#actionbtnBrowse, #actionbtnSave {
margin:0 !important;
width:60px;
}

JQuery

$("#browse").click(function () {
$("#test").click();
})

$("#save").click(function () {
alert('Run a save function');
})

$("#clear").click(function () {
$('#testfile').val('');
})

$('#test').change(function () {
$('#testfile').val($(this).val());
})

还需添加到外部资源选项卡:

https://github.com/necolas/css3-github-buttons/blob/master/gh-buttons.css


5

不需要虚假的div!没有JavaScript也不需要额外的html。只使用css就可以实现。

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

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

--> 演示


请 @Misha 选择您最喜欢的答案作为正确答案。谢谢。 - Despertaweb

4

除了 Reigel,下面这个实现方式更为简单。你也可以在多个文件输入字段上使用此解决方案。希望这能帮到一些人 ;-)

HTML(单个输入)

<input type="file" name="file" />

HTML (multiple input)

<!-- div is important to separate correctly or work with jQuery's .closest() -->
<div>
  <input type="file" name="file[]" />
</div>

<div>
  <input type="file" name="file[]" />
</div>

<div>
  <input type="file" name="file[]" />
</div>

JavaScript

// make all input fields with type 'file' invisible
$(':file').css({
  'visibility': 'hidden',
  'display': 'none'
});

// add a textbox after *each* file input
$(':file').after('<input type="text" readonly="readonly" value="" class="fileChooserText" /> <input type="button" value="Choose file ..." class="fileChooserButton" />');

// add *click* event to *each* pseudo file button
// to link the click to the *closest* original file input
$('.fileChooserButton').click(function() {
    $(this).parent().find(':file').click();
}).show();

// add *change* event to *each* file input
// to copy the name of the file in the read-only text input field
$(':file').change(function() {
    $(this).parent().find('.fileChooserText').val($(this).val());
});

2

这是一个使用jQuery的示例,我已在Firefox 11、Chrome 18和IE9上进行了测试。因此,在我看来,它与浏览器相当兼容,尽管我只使用这三个浏览器。

HTML

这是一个基本的“可自定义”的HTML结构。

<span>
    File to Upload<br />
    <label class="smallInput" style="float:left;">
        <input type="file" name="file" class="smallInput" />
    </label>
    <input type="button" class="upload" value="Upload" style="float:left;margin-top:6px;margin-left:10px;" />
</span>

CSS

这是我的CSS样例:

label.smallInput {
    background:url(images/bg_s_input.gif) no-repeat;
    width:168px;
}

JavaScript

这是一个非常重要的技术。

/* File upload magic form?? */
$("input.smallInput[type=file]").each(function(i){
    var id      = "__d_file_upload_"+i;
    var d_wrap  = $('<div/>').attr('id',id).css({'position':'relative','cursor':'text'});

    $(this).wrap(d_wrap).bind('change blur focus keyup click',function(){
        $("#"+id+" input[type=text]").val($(this).val());
    }).css({'opacity':0,'zIndex':9999,'position':'absolute'}).removeClass('smallInput');

    obj = $(this);

    $("#"+id).append($("<input/>").addClass('smallInput').attr('type','text').css({'zIndex':9998,'position':'absolute'}).bind('click',function(e){obj.trigger('click');$(this).blur();}));
    obj.closest('span').children('input.upload[type=button]').bind('click',function(e){
        obj.trigger('click');
        $(this).blur();
    });
});
/* ************************ */

说明

HTML代码非常简单,只是一个简单的元素,我包括按钮,以便可以将其命名独立于其他内容,当然这可以包含在JavaScript中,但简而言之,我有点懒。该代码搜索所有具有文件类型小型输入框类的输入框,这允许您定义默认的HTML和回退表单结构,以防浏览器决定变得麻烦。

此方法仅使用JavaScript来确保交付,不会改变任何与文件输入相关的浏览器行为。

您可以修改HTML和JavaScript使其非常强大,但此代码足以满足我的当前项目,因此我不认为会对其进行任何更改。

注意事项

  • 不同的浏览器以不同的方式处理文件输入的值,在Chrome中会在Windows机器上导致c:\fakeroot\。
  • 使用匿名函数(缺乏更好的词语),这意味着如果您有太多文件输入,则可能会导致浏览器在处理时变慢。

2
今天遇到了同样的问题,但似乎有一种简单的方法来使用自己的样式 - 隐藏输入框,并为相关的标签设置样式:
<div class="upload">
  <label for="my-input"> Upload stuff </label>
  <input type="file" id="my-input" name="files[]" />
</div>

CSS:

.upload input{
  display: none;
}

.upload label{
  background: DarkSlateBlue;
  color: white;
  padding: 5px 10px;
}

适用于最新版本的Chrome、Firefox和IE 10。未测试其他浏览器。


在Safari 5.1.7上无法运行,真遗憾,这是一个非常好的技巧。 - Julian

2
Reigel的回答虽然表达了这个想法,但并没有任何风格。最近我遇到了这个问题,尽管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>

希望这有所帮助!!!

1

这里提供了一个解决方案,其中包含一个文本字段,用户可以在其中输入服务器上文件副本的(相对)路径名(如果获得授权),以及一个提交按钮,用于浏览本地系统中的文件并发送表单:

<form enctype="multipart/form-data" action="" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" />
<p><input type="file" name="upload_file" id="upload_file" size="40"/></p>
<p><input type="text" id="upload_filename" name="upload_filename" size="30" maxlength="100" value="<?php echo htmlspecialchars($filename, ENT_COMPAT, 'UTF-8'); ?>"/>
<input type="submit" class="submit submit_upload" id="upload_upload" name="upload_upload" value="Upload"/></p>
</form>

脚本部分隐藏文件输入,如果用户点击提交按钮,则单击它,如果用户已选择文件,则提交表单。如果用户尝试上传没有输入文件名的文件,则首先将焦点移动到文件名文本字段。

<script type="text/javascript">
var file=$('#upload_file');
var filename=$('#upload_filename');
var upload=$('#upload_upload');

file.hide().change(function() {if (file.val()) {upload.unbind('click').click();}});

upload.click(function(event) {event.preventDefault();if (!filename.val()) {filename.focus();} else {file.click();}});
</script>

只需为提交按钮设置样式,即可获得完美的结果:

.submit {padding:0;margin:0;border:none;vertical-align:middle;text-indent:-1000em;cursor:pointer;}
.submit_upload {width:100px;height:30px;background:transparent url(../images/theme/upload.png) no-repeat;}

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