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%;
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.

No related posts.

This entry was posted in css3. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.


  1. Trover
    Posted April 11, 2012 at 5:07 pm | Permalink

    Thanks, this article wasme util

  2. cat
    Posted September 8, 2012 at 1:57 am | Permalink

    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?

  3. Posted October 13, 2012 at 11:19 pm | Permalink

    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.

  4. Mohammad Asad Ansari
    Posted October 23, 2012 at 2:29 pm | Permalink

    That article is very userful, and work for crome properly.

  5. Posted February 22, 2013 at 12:57 pm | Permalink

    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.

  6. Anonymous
    Posted March 14, 2013 at 2:44 pm | Permalink

    Thanks really it worked.. THANK YOU :)

  7. Posted April 8, 2013 at 5:32 pm | Permalink

    Thank you, this was very useful. Could you please tell me how to use an image for the button?

  8. admin
    Posted April 8, 2013 at 8:10 pm | Permalink

    A simple technique which uses images is described here 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.

Post a Comment

Your email is never published nor shared. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>