4

I have tried many different techniques to style the input[type="button"] that is inside of an input[type="file"].

I have found one technique that uses pure CSS that allows the user to see the file name they have selected. However, it leaves out one particularly popular browser, firefox.

I have found several ways to "do" this by using JS or by simply outright hiding the output box for filename.

Links to JS or hiding methods.:

  1. www.quirksmode.org
  2. www.shauninman.com
  3. www.appelsiini.net

The pure CSS methods I completely stumbled upon in chrome, and afterwards found again in an answer to styling an input type file button

This CSS method works by selecting the element by its pseudo class.

In Google Chrome this is done by:

input.formelement::-webkit-file-upload-button {background-color: #443}

Where, input.formelement is the class of my file upload form and -webkit-file-upload-button is the browser-specific pseudo element.

In Internet Explorer (10+) this is done by:

input.formelement::-ms-browse {background-color: #443}

Once again, input.formelement is the class of my file upload form and -ms-browse is browser-specific pseudo element.

Is there any way to do this in FireFox without Javascript?

Community
  • 1
  • 1
ZizzyDizzyMC
  • 73
  • 2
  • 9

2 Answers2

2

I don't believe there is a way to do this in Firefox using CSS only.

There is also no way to style or change the text "No file selected." That file name label also appears differently in various browsers.

If you truly want a cross-browser solution, your best choice is still to use a fake "button" that triggers clicks on the actual hidden button. Using JS may be the obvious choice, but not the only way:

JS Method:

// JS - DOM Elements
var browse_button = document.getElementById('browse-button');
var file_input = document.getElementById('file-input');

// Handler to trigger click on file input
browse_button.addEventListener('click', function(e) {
   file_input.click();
});
/* CSS to hide file input */
#file-input {
  display: none;
}
#browse-button {
  /* TODO: styles */
}
<!-- Simple HTML -->
<input type="file" id="file-input" />
<button type="button" id="browse-button">Browse</button>

Pure HTML/CSS Method:

A simple HTML + CSS can also work, especially if you don't need the "file name label". A quick-dirty HTML + CSS solution:

* {
  box-sizing: border-box;
}
input[type=file] {
  position: absolute;
  top:-5px; /* size of border */
  left:-5px; /* size of border */
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  width: 240px;
  height: 50px;
  border: 1px solid red;
  opacity: 0; /* hide actual input */
  cursor: pointer
}

.fakeFileButton {
  position: relative;
  margin: 0;
  padding: 0;
  width: 240px; /* same as button */
  height: 50px; /* same as button */
  background-color: rgb(50,50,238);
  border: 5px solid rgb(128,128,128);
  font-size: 18px;
  color: rgb(255,255,255);
  text-align: center;
  line-height: 40px;
}
.fakeFileButton:hover {
  background-color: rgb(100,150,255);
  color: rgb(0,0,0);
}
<div class="fakeFileButton">
    Browse File on Computer
    <input type="file">
</div>

If you want to add a fake file name label, it's also possible, but you have to use JS to set up a handler to observe for change events, with a callback that reads the real_input.value and write it into fake_label.innerHTML.

light
  • 4,157
  • 3
  • 25
  • 38
  • I found a way to do what I need but it can not be done for the end user. FireFox uses a user agent stylesheet but unlike any other browser, it can not be overridden. After some digging I found this: http://prntscr.com/7snuy2 Despite having a user agent stylesheet capable of changing shadow-dom objects Mozilla seems to have taken the road easiest to travel. [Mozilla.org](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Forms/Advanced_styling_for_HTML_forms) – ZizzyDizzyMC Jul 14 '15 at 18:18
  • As far as I know, you can't alter user agent stylesheets. So how did you "do it but not for the end user"? Don't really understand you there. – light Jul 14 '15 at 18:27
  • I did it with a quick and simple thing that changes the button cursor for `input[type="file"] > input[type="button"]` from the default to my custom hitmarker cursor. I did it by editing the forms.css inside of omni.ja, which in the following screenshot can be downloaded from one of my servers. (If you wish to test yourself. Just make a backup of your omni.ja and paste mine in place and restart FireFox and navigate to a site with a button.) [Screenshot](http://i.imgur.com/zLwkRus.png) – ZizzyDizzyMC Jul 14 '15 at 19:26
  • @light: Could you give more details about using a button element to trigger a click on a hidden input element? – David R Tribble Feb 23 '16 at 22:00
  • @DavidRTribble added code sample of JS method in answer. – light Feb 24 '16 at 07:02
0

For anyone finding this question in the 2020s, from Firefox 82 onwards you can use the ::file-selector-button pseudo element. It's worth noting this is also supported in Chromium and Safari now too.

Luke W
  • 1
  • 1