From a UI perspective, uploading files from a web page is handled by the file form input. But until very recently, this method had serious issues: it wasn’t supported on mobile.

Starting this month, the file input is supported natively in iOS9 and Android 5, making uploads a lot easier for everyone. Over time, it’s likely that this support will also substantially replace the native apps that traditionally filled this role. This makes now the right time to look at the form element in depth.

The Basics

The element itself couldn’t be much simpler:

<input type="file">

Of course, this will usually be associated with a bunch of markup, both to allow the input data to be processed, and for accessibility:

<form method="post" action="upload.php" formenctype="multipart/form-data">
    <label for="upload">Upload your picture:</label>
    <input type="file" name="upload" id="upload">
</form>

Which creates:

Like the color input and other form elements, the file input will use the native OS for dialog boxes and UI when the Select file button is clicked.

Limitations

You can limit the file input to accepting certain kinds of files by specifying their MIME type in the accept attribute, with an optional wildcard (*) to allow files of a particular type:

<input type="file" accept="image/*" name="upload" id="upload">

Files that don’t match the criteria (in the example above, anything that is not an image file) will be grayed out or disabled in the file dialog.

You can also accept multiple files at once by using the word as a “boolean” attribute:

<input type="file" multiple accept="image/*" name="upload" id="upload">

iOS does not currently support the multiple attribute, and only allows the user to upload files from particular stores in the device: a live photo from the camera, the photo roll, and online storage services like iCloud and Dropbox.

Customization

The file input isn’t terribly attractive, and doesn’t easily allow CSS customisation (although it is possible). There’s a small trick you can use to turn off the input entirely and substitute your own UI, while keeping the functionality of the element intact. First, create a file input, and next to it, a button element:

<label for="fileUpload" accept="image/*">Upload your image</label>
<input type="file" id="fileUpload">

Then add some :

var fileUpload = document.getElementById("fileUpload"),
uploadLabel = document.querySelector("label[for='fileUpload']"),
fileInsert = document.createElement("button");
fileInsert.id = "fileSelector";
fileInsert.innerHTML = uploadLabel.innerHTML;
fileUpload.parentNode.insertBefore(fileInsert, fileUpload.nextSibling)
fileUpload.style.display = "none";
uploadLabel.style.display = "none";
fileInsert.addEventListener('click', function(e){
    e.preventDefault();
    fileUpload.click();
}, false);

The result can be seen at the top of this article: the script hides the file input and substitutes a <button> element; clicking on the button will initiate the file dialog by creating a click event on the hidden element. The button can then be styled however you wish with CSS:

#fileSelector {
    font-size: 1.3rem; padding: .5rem 1rem;
    background: hsl(50,100%,50%);
    font-family: Avenir, sans-serif;
    border-radius: 5px;
    cursor: pointer;
    display: block;
    margin: 0 auto;
}

A First Step

Of course, this is only the client-facing front-end UI aspect of uploading a file: there are many different methods for actually handling the file, from the HTML5 File API in JavaScript to PHP. A simple File API version is shown above; I’ll go into far more detail about that in the next article.

It should also be mentioned that there are other UI possibilities for dealing with file uploads, including drag-and-drop interfaces, which I’ll also cover in a future article.

Photograph by blizzy78, licensed under Creative Commons

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/KdybXW