How to customise a file upload control

Published 02 May 2017 category: code

If your website lets users upload files, you have probably compared the default file upload control with custom solutions. In this article I will show you can have both, using a method that uses the default input, but looks completely custom.

The default file upload

This is a default file upload:

<input type="file" id="file-upload" />
<label for="file-upload">Upload a file</label>

It is one of those HTML elements that has a lot of usability and accessibility built in.

To name a few things that you get for free when using the native <input type=file>:

File input that matches your brand

Something you probably don’t get for free is a smooth integration with your brand’s design guidelines. They might prescribe buttons to be blue or rounded corners everywhere.

The HTML example above related the input with a corresponding label. I used corresponding for and id attributes, but wrapping the input inside a label works just as well.

In all browsers, you will find that you don’t actually have to click the input to activate it: clicking the label will do. Because of this, the trick, which I learned from Krijn, is simple: hide the <input/> and style the <label>.

Hide the input

You want to hide the input, but do that in a way that screenreaders don’t assume it does not exist. The method for hiding is to make it ‘visually’ hidden, but not actually hidden to assistive technologies.

This is one way:

input[type="file"] { 
  opacity: 0; /* make transparent */
  z-index: -1; /* move under anything else */
  position: absolute; /* don't let it take up space */

There are various different approaches to this, the important thing is that the method does not render the input unusable (as visibility: hidden would, for example), or move it off screen (as left: -9999em would), as that would move any native error messages off screen as well.

Style the label

Now, only the label is visible and you can style it however you like. You can make it look like a button, add background gradients, drop shadows, whatever your heart desires.

Add focus styles

It would be good to add the focus styles that your input had to the label. You can select this in CSS as follows:

input[type="file"]:focus + label {
  outline: 2px solid;  /* example focus style */


To make a custom file upload control, use a standard file upload and label, then visually hide the input and style the label.

Update: On Twitter, Phil pointed out that if you use the above example, users can’t see the file name of what they’ve uploaded. This is a great point; in my own implementation I’ve used some JavaScript to access the input’s files property onchange of the input, which I then inserted into the page if it had changed (I’ve created a Codepen to show how to do this)

Leave a comment
Posted a response to this?

This website uses Webmentions. You can manually notify me if you have posted a response, by entering the URL below.