Styling an input type=”file”

Maria Cristina Di Termine

This blog post is about a simple but tricky argument: the input file. If you ever had to use it, you for sure noticed how ugly can be the style you are forced to show by the browser. Unlikely the other types of inputs, the input file is not easy to overwrite with CSS. To do that we need basely to hide the ugly default button and use another element as substitute.
First thing first, hide the input file
Now let’s imagine to have this input with a class that we will call ‘upload’ :

<input type="file" name="file" id="file" class="upload" />

How can we make it disapper? You might think that the easiest solution is using the CSS properties such as display:none or visibility:hidden. Well, I’m sorry to tell you that this will not help us because it will just impede the right functionality of the input and the file we’ll select to be uploaded, won’t be sent to the server. Plus the input will be excluded from the tab order which means that your website won’t be very accessible anymore. We don’t want that! right?
The solution to hide the input is to set a couple of property to the class upload like this:

.upload {
    width: 0.1px;
    height: 0.1px;
    opacity: 0;

I recommend to don’t set 0px for width and height because that will again exclude the input out the tab order. Now you will notice that now the ugly button is no longer visible indeed. But how can we replace it? The answer is, using a label element!

Replace the button using label
Why a label? Because clicking on the label we can trigger the event of the input using the attribute “for”. So let’s edit our html tags to:

<input type="file" name="file" id="file" class="upload" />
<label for="file">Choose a file</label>

Here we go, as you can see the label already works as we aspected! Now let’s make our new button user friendly and test if everything works correctly!

.upload + label {
    width: 200px;
    font-size: 1em;
    font-weight: 500;
    color: white;
    line-height: 2.6em;
    text-transform: uppercase;
    text-align: center;
    background-color: #ef494f;
    display: inline-block;
    border-radius: 10px;
    box-shadow: 0px 3px 0px #a73337;
    transition: 150ms;

.upload:focus + label,
.upload + label:hover {
    background-color: #ff6c71;
    box-shadow: 0px 5px 0px #d03338;

A little tip to make your label really accessible is to style even the :focus statement:

.upload:focus + label {
    outline: 1px dotted #000;
    outline: -webkit-focus-ring-color auto 5px;

Like this we will indicate even when the label is focussed. Add also -webkit-focus-ring-color to make our style cross-browser too.
Hoping that this post can be useful here you can check out a little demo.


you might also like