How can I style a file input field in Firefox?

I am currently doing the front end for a site with looooads of forms, all styled up and looking pretty in IE, but I've just noticed that in Firefox the file input fields aren't responding to any of my styles, all the other types of input fields are fine. I've checked it in Firebug and its associating the correct styles to it, but not changing how it looks.

If this isn't a complete brain fart on my behalf, then is this a known issue in Firefox? And if so, how have I never noticed it before?

Here is a sample of the code.

CSS:

form.CollateralForm input,
form.CollateralForm textarea
{
    width:300px;
    font-size:1em;
    border: solid 1px #979797;
    font-family: Verdana, Helvetica, Sans-Serif;
}

HTML:

<form method="bla" action="blah" class="CollateralForm">
   <input type="file" name="descriptionFileUpload" id="descriptionFileUpload" />
</form>

I've also tried applying a class to it but that doesn't work either.


Solution 1:

Many of the answers above are quite old. In 2013 a much simpler solution exists: nearly all current browsers...

  • Chrome
  • IE
  • Safari
  • Firefox with a few-line fix

pass through click events from labels. Try it here: http://jsfiddle.net/rvCBX/7/

  • Style the <label> however you you would like your file upload to be.
  • Set for="someid" attribute on the label
  • Create a <input id="someid"> element, that's hidden.

Clicking the label will passthrough the event to the fileupload in Chrome, IE, and Safari.

Firefox requires a very small workaround, which is detailed in this answer.

Solution 2:

Firefox can be hacked using the HTML input size attribute: size="40" while using a css width to control the full width of the field + button in layout

Solution 3:

Let's say you have your input:

<input style="display:none" id="js-choose-file" type="file">

Create a fake button using jQuery.

<a id="js-choose-computer" href="javascript:void(0);">From Computer</a>

Style the above button any way you like. Then:

$("#js-choose-computer").on("click", function() {
  $("#js-choose-file").click();
  return false;
});

Solution 4:

As of Firefox 82, hacks are no longer necessary, per the ::file-selector-button pseudo selector. Current versions of Webkit/Blink browsers (Chrome, Edge, Safari, Opera) don't support it at the moment, but it can be dealt with using the ::-webkit-file-upload-button non-standard pseudo-class.

This way, your HTML can be kept semantic, and no hacks are needed.

Example code from MDN reference above:

HTML

<form>
  <label for="fileUpload">Upload file</label>
  <input type="file" id="fileUpload">
</form>

CSS

input[type=file]::file-selector-button {
  border: 2px solid #6c5ce7;
  padding: .2em .4em;
  border-radius: .2em;
  background-color: #a29bfe;
  transition: 1s;
}
 
input[type=file]::file-selector-button:hover {
  background-color: #81ecec;
  border: 2px solid #00cec9;
}