Many of the answers above are quite old. In 2013 a much simpler solution exists: nearly all current browsers…
- 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.
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.