Posting in this thread because it's old, outdated and because others (like me) may find it from Google and wonder what they can do to create better looking input[type=file] boxes!
The short answer is still: You can't.
However, you CAN actually make a pretty good stab at making something you can style, and then controlling the file input appropriately, if you're prepared to use a little JavaScript.
First up, HTML along these lines:
<a href="#" class="btn btn-upload">Choose your photo</a>
<div class="fileupload">
<label for="picture">Your Image:</label>
<input type='file' name="picture" id="picture" enctype = "multipart/form-data" runat="server" required />
</div>
This allows you to use the fileupload
div to 'hide' the real control - However, you SHOULD NOT use display:none
- Many browsers will see this as a security risk. Instead, try position:relative
with left:-99999px
, or a height:0px
with overflow:hidden
. If you need to turn this off for any reason (Such as needing to support really old IE) then you can use an IE stylesheet or Modernizr and reverse the css to show the normal upload and hide your 'fake'.
Now, style your btn-upload
appropriately. However you want it.
Use JavaScript to click the input file for you, when someone clicks your 'fake' (The following assumes you use jQuery):
$(".btn-upload").click(function () {
$(".fileupload input").trigger('click');
return false;
});
What's more, if you want to alter the appearance of your styled file input fake, or have your page react in any way when a user has selected a file, you can do so by using the change event. The following example will display the image a user is about to upload, in an img tag with an id of image-preview
(This won't work in IE below 10):
$('input[type=file]').change(function () {
var input = $(this);
if (input[0].files && input[0].files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#image-preview')
.attr('src', e.target.result);
};
reader.readAsDataURL(input[0].files[0]);
}
});
You can also get access to the filename if you want to use javascript to display it somewhere:
$('input[type=file]').change(function () {
var input = $(this);
if (input[0].files && input[0].files[0]) {
var file = input[0].files[0]
if (file) {
//Put the file name into a div with the id of 'filename'
$('#filename').html(file.name);
}
}
});
Using all of this, you can make a pretty good upload button which looks really nice and still works. I also recommend using feature detection and hiding all of this on browsers where file uploading is not supported (LOOKING AT YOU, OLD IOS!)
Example of file upload function detection:
function checkForInputFile() {
var elem = document.createElement("input");
elem.type = "file";
if (elem.disabled) return false;
try {
elem.value = "Test"; // Throws error if type=file is implemented
return elem.value != "Test";
} catch(e) {
return elem.type == "file";
}
}
if(checkForInputFile()){
console.log('i support file input type!');
} else {
console.log('i dont :(');
}
( The above is based on the correct answer here: Detect if <input type="file" /> is supported )
Finally, what if we want a button to CLEAR a file type input? Well, again, for security reasons, this isn't easy. But it is possible! This solution is my favourite: Clearing <input type='file' /> using jQuery
And if you're too lazy to open the link, here's an example of that approach, using my example html, assuming we add a link with the id remove-file
somewhere on the page:
function resetFormInputElement(e){
e.wrap('<form>').closest('form').get(0).reset();
e.unwrap();
}
$('a#remove-file').click(function () {
//Clear input file
resetFormInputElement($('.fileupload input'));
return false;
});