STYLING FILE INPUTS WITH CSS AND THE DOM
File inputs (<input type="file" />
) are the bane of beautiful form design. No rendering engine provides the granular control over their presentation designers desire. This simple, three-part progressive enhancement provides the markup, CSS, and JavaScript to address the long-standing irritation.
Before we get down to the nitty gritty details, check out the demo or, if you’re a Mint user, check out your settings page in the Mint Account Center (requires login).
The Markup
<label class="cabinet">
<input type="file" class="file" />
</label>
The file input is given a class of file
and wrapped in an element with a class of cabinet
. (The type of wrapper element and actual class names are not set in stone and can be changed via properties of the SI.Files
object to avoid conflicts as necessary.)
The CSS
.SI-FILES-STYLIZED label.cabinet
{
width: 79px;
height: 22px;
background: url(btn-choose-file.gif) 0 0 no-repeat;
display: block;
overflow: hidden;
cursor: pointer;
}
.SI-FILES-STYLIZED label.cabinet input.file
{
position: relative;
height: 100%;
width: auto;
opacity: 0;
-moz-opacity: 0;
filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);
}
The first three properties of the wrapper element style should be changed to reflect the width, height and url of your custom button image. Everything else can be left alone. (Different buttons can be used for different file inputs by adding an additional class to the wrapper element and styling accordingly.)
The JavaScript
First include the SI.Files
library. Simple enough:
<script type="text/javascript" src="/path/to/si.files.js"></script>
Then, either in your onload event handler or at some point after your file inputs appear in the source, call:
SI.Files.stylizeAll();
The library also offers two alternate methods of styling file inputs. Given an element id:
SI.Files.stylizeById('input-id');
Or given an element node:
SI.Files.stylize(HTMLInputNode);
Both alternates are useful when the form that contains your file input is loaded via Ajax.
How it works
We start with a simple replacement. The custom button image is set as the background-image of our wrapper element and dimensions are set to match.
Next we set the opacity of the file input itself to zero, effectively making it invisible but still clickable (something that can’t be achieved with display: none;
or visibility: hidden;
).
Finally, the JavaScript keeps the button portion of the the file input underneath the pointer whenever the mouse enters the wrapper element. A class of SI-FILES-STYLIZED
(also configurable) is applied to the html
element of the page for use as a styling context for compatible browsers.
Compatibility
This solution is known to work in:
- IE 5.5+
- Firefox 1.5+
- Safari 2+
It is known to degrade gracefully in:
- Opera
- IE 5.01
The SI.Files library and example files have been downloaded 3621 times.