How to style input tag file uploads in Webkit (Chrome, Safari)

If you’ve ever been tasked with creating a consistent user experience across all web browsers you’ve probably had a real challenge styling form input elements. Historically IE has been the most challenging to style but with file input elements webkit is almost impossible to change it from the default “choose file” dialog. Typically the file input is styled by setting it’s opacity to 0 and absolute positing it over an image of a browse button with whatever style is desired. The downside of this is that is requires JavaScript to update a text input element after a file is chosen with the file selection dialog. This technique uses pure CSS to present a consistent interface to all major browsers with a few vendor CSS prefixes.

Basic unstyled file input:

Screenshots of popular browsers:
Soon to be added.

As you can see the file upload buttons all look about the same with the exception of webkit based browsers, Chrome and Safari which show the “Choose File” button with the value of the file chosen shown to the right of that. This technique will change not only the content of the button but it’s position relative to the text of the file chosen.

input[type=file] {
-webkit-appearance: textfield;
position: relative;
-webkit-box-sizing: border-box;
}
input[type=file]::-webkit-file-upload-button {
width: 0;
padding: 0;
margin: 0;
-webkit-appearance: none;
border: none;
}
/* "x::-webkit-file-upload-button" forces the rules to only apply to browsers that support this pseudo-element */
x::-webkit-file-upload-button, input[type=file]:after {
content: 'Browse...';
display: inline-block;
left: 100%;
margin-left:3px;
position: relative;
-webkit-appearance: button;
padding: 3px 8px 2px;
}

Now our input field looks like:

Cool huh?
So how does this work?
The secret is in “input[type=file]::-webkit-file-upload-button” which lets us select the “Choose File” button itself. We hide this and then add our own button with “input[type=file]:after” it is preceded by “x::-webkit-file-upload-button, ” which causes all browsers that don’t support the -webkit-file-upload-button selector to ignore the rule. If we didn’t add this other browser might try to add the content which might mean there would be two browse buttons displayed. “-webkit-appearance” is a useful rule to give any element whatever native look we like here we use it to make the :after content look like a button and the regular input element to look like a textfield. Now webkit’s style will match IE and Firefox with the brows button located after the box with the selected file.

9 thoughts on “How to style input tag file uploads in Webkit (Chrome, Safari)”

  1. Very nice overview of styling file inputs. You helped me resolve something that was driving me bonkerz today. Are webkit browsers trying to be wonky on purpose?

  2. Thanks. Your write-up has helped me. I had a different method, but yours is better. For Chrome, I just created a new button out of a pseudo element and hide the default button.

  3. Thank you so much for posting these crazy CSS skills.

    I’ve been messing about with JS solutions to this problem for hours (and days…) – who’d have thought that good old CSS was the solution?

    Thanks again.

  4. A simple technique which uses images is described here http://www.quirksmode.org/dom/inputfile.html. It uses an image tag with a invisible file input absolutely positioned over it. It’s made invisible with opacity:0. Works very well but requires a small amount of js if you want to update the page with an indication of the filename the user chose.

Leave a Reply

Your email address will not be published. Required fields are marked *