Styling File Inputs

The most difficult of all the form fields to style are file input fields. In fact it is completely impossible to style those fields directly. This makes things rather awkward as some browsers display this input type as if it were an input field and a button while others display it as if it were a button and some plain text.

While it is impossible to style the field directly we can achieve the equivalent result by hiding the field and displaying instead something that we can style. So as to not completely reinvent the wheel I used the solution offered at quirksmode as my starting point and have corrected for a few things that the author of that page overlooked. Note that quirksmode in turn credits Michael McGrady for part of the solution presented there.

This solution will only work in those browsers that support opacity. Basically, we use opacity to make the file input invisible and position the button element that we can style directly behind it so that when our visitor thinks they are clicking on our nicely styled button they are actually clicking on the file input button. Since those browsers that don't support opacity will display the ordinary file input in front of our replacement where the CSS to position one over the other is supported the only time we have an issue with what is displayed is in those browsers that don't support CSS. As the only way to display the selected file after the button is clicked is to use JavaScript. By generating the button from within the JavaScript and only processing the change in browsers modern enough to work when this approach is used we can leave the original input alone for older browsers as well as for ones that have JavaScript turned off.

Since actually being able to update the file input to remove a selected file is only possible in some browsers and is not possible with this replacement approach I have rearranged the HTML that my JavaScript generates to more closely match what you see for an unstyled file input in Google Chrome or Safari. This gives both a consistent appearance and consistent functionality across all modern browsers when the script runs.

Another consideration in my redesign of the code is the addition of labels for the file inputs and making sure that multiple file inputs display and process correctly (when I originally added a second file input the inputs displayed on top of one another).

CSS

span.fileinputs {
position: relative;
}
span.fakefile {
position: absolute;
top: 0px;
left: 0px;
z-index: 1;
}
input.file {
position: relative;
text-align: right;
z-index: 2;
padding-bottom:2em;
}
input.hidden {
-moz-opacity:0 ;
filter:alpha(opacity: 0);
opacity: 0;
}
span.fakefile span {
font-size: 0.6em;
white-space:pre;
}

JavaScript

(function() {
"use strict";
var ffup, btn, x, i, cn;
if (!document.createElement || !document.getElementsByTagName) return;
ffup = document.createElement('span');
ffup.className = 'fakefile';
btn = document.createElement('button');
btn.innerHTML = 'Choose File';
ffup.appendChild(btn);
ffup.appendChild(document.createElement('span'));
x = document.getElementsByTagName('input');
for (i=x.length-1;i >= 0; --i) {
if (x[i].type !== 'file' || x[i].parentNode.className !== 'fileinputs') continue;
x[i].className = 'file hidden';
cn = ffup.cloneNode(true);
x[i].parentNode.appendChild(cn);
x[i].relatedElement = cn.getElementsByTagName('span')[0];
x[i].onchange = x[i].onmouseout = function () {this.relatedElement.innerHTML = this.value.slice(this.value.lastIndexOf('\\')+1);}
}
})();

One thing that you will note is that having made the file input invisible by setting its opacity to zero and having inserted a button and a span in its place that I have not applied any additional styling to the example on this page (although I have made sure there is enough space under the input field to display the file name if there isn't enough space for it inside of the space the original input field would take up). Now that we have replaced the file input with a button in what is visible in our page we can style the button the same way you'd style any button in your page. I'll leave that styling to you.

 

This article written by Stephen Chapman, Felgall Pty Ltd.

go to top

FaceBook Follow
Twitter Follow
Donate