How to Create a Custom File Input (For Use With the HTML5 File APIs)

I’m working on an HTML/JS application that lets users work with local files directly in the browser, and I’m using some new HTML5 APIs to access local files. It works great (in Chrome and Firefox, anyway — see note below), however my UI calls for a custom file input rather than the default (and usually pretty ugly) button-and-path input. Fortunately, customization is easy in this case. The trick is to create your own UI treatment (in my case, just a link), then use the click() function on a hidden file input to bring up the file dialog.

In Firefox, you can use the display:none style as noted in this Mozilla Developer Network documentation, however this won’t work in Chrome or Safari (although FileReader is currently not supported in Safari, you might as well think ahead for when it is). A better way of doing it, therefore, is to use visibility:hidden.

The only problem is that when something is hidden using its visibility property, it’s still actually in the DOM, and space is therefore allocated for it even though you can’t see it. If you want to get your file input completely out of the way, therefore, you can use something like this:

<input type="file" id="fileInput" onchange="handleFiles(this.files)" style="visibility:hidden;position:absolute;top:-50;left:-50"/>

Your file input will still be in the DOM (even though it’s hidden and off-screen), however it won’t take up any visual space.

Here’s the full HTML code:

<a href="javascript:onLoad();">Load a File!</a>
<input type="file" id="fileInput" onchange="handleFiles(this.files)" style="visibility:hidden;position:absolute;top:-50;left:-50"/>

And here’s the JavaScript code:

function onLoad() {
    id('fileInput').click();
}

function handleFiles(files) {
    var file = files[0];
    var reader = new FileReader();
    reader.onload = onFileReadComplete;
    reader.readAsText(file);
}
  
function onFileReadComplete(event) { 
  // Do something fun with your file contents.
}

Note that this code is only going to work in current versions of Chrome and Firefox, but is expected to work in future versions of IE (10) and Safari (6).

One Response to How to Create a Custom File Input (For Use With the HTML5 File APIs)

  1. Kevin Hoyt says:

    Another option I’ve used is to put the file input in a div element, with the background image of the div element being my custom button image. Set the opacity of the input to 0 and it is not visible, but still part of the clickable DOM (as opposed to visibility hidden). The div element will also then still respond to mouse/touch events to swap out the background image. Listen for the change event on the input and you’re all set. Don’t forget to make sure the size of the (now hidden) input matches the size of the button/div element.