Thursday, January 21, 2010

CSS Style <input type=”file”> tags


Inputs of type=”file” are probably the hardest tags to style in html. Due to security issues browsers don’t allow you to change it too much.
Of course we have tricks but since each browser makes its own implementation of the control (and it’s poorly documented stuff) the tricky part is to find something that works for all browsers.
If you google for it you’ll find a few tutorials that are hard to understand and use too much javascript, jquery and css.
I found a relatively simple way to achieve this and I’ll try to make it easy to understand. It goes in 4 steps.
STEP 1 – Create a text box and a input “type file”
Start with a textbox and a div with a input “type file” inside of it. The div should be the size of the “browse…” button that you want to use.
The only tricky part for now is the overflow property in the css class of the div being set to hidden. That causes the overflowing content of the div to be hidden from sight. See it in the screenshot.
html:
<input id="fileName" class="file_input_textbox" readonly />
 
<div class="file_input_div">
  <input type="file" />
</div>
css:
.file_input_textbox
{
 float: left
}

.file_input_div
{
  position: relative; 
  width: 100px; 
  height: 23px; 
  overflow: hidden;
}
screenshot:
image
STEP 2 – The fun part: oversize the input  “type=file”
Now we have to make the button part of the input “type=file” show in the div and completely fill it. Aligning it to the right is now enough because the different browsers act differently in this case.
So, the big trick in this tutorial? Oversize the control. How? Just set its font size to an absurd size (probably 30px will be enough, though).
html:
<input type="text" id="fileName" class="file_input_textbox" readonly="readonly">

<div class="file_input_div">
  <input type="file" class="file_input_hidden"  />
</div>
css:
.file_input_hidden
{
  font-size: 23px; 
  position: absolute; 
  right: 0px; 
  top: 0px; 
  opacity: 0; 
}
screenshot:
image
STEP 3 – Make the input “type=file” invisible and put your customized button behind it.
Making the file input invisible doesn’t mean that you cant click it. So, make it invisible, put a customized button behind it.
That way, you will see your customized button but when you click it, you will in fact be clicking the real (invisible) browse button (the one that is oversized, overflowing, over the customized button, remember?)
You can customize your browse button by changing the “file_input_button” css class.
html:
<input type="text" id="fileName" class="file_input_textbox" readonly="readonly">
 
<div class="file_input_div">
  <input type="button" value="Search files" class="file_input_button" />
  <input type="file" class="file_input_hidden" />
</div>

css:
.file_input_button
{
 width: 100px; 
 position: absolute; 
 top: 0px;
 background-color: #33BB00;
 color: #FFFFFF;
 border-style: solid;
}

.file_input_hidden
{
 font-size: 45px; 
 position: absolute; 
 right: 0px; 
 top: 0px; 
 opacity: 0; 
 
 filter: alpha(opacity=0); 
 -ms-filter: "alpha(opacity=0)"; 
 -khtml-opacity: 0; 
 -moz-opacity: 0;
}
screenshot:
image
STEP 4 – Final step: Fill the text box with the name of the selected file
If you tried the previous steps, will have noticed that after you select a file, nothing shows in the text box. That’s because the file name is indeed being written in the hidden input “type=file”.
So, in this final step you shall add a simple javascript instruction to the onchange event of the input “type=file” tag. That instruction copies its value (the filename) to the text box.
html:
<input type="text" id="fileName" class="file_input_textbox" readonly="readonly">
 
<div class="file_input_div">
  <input type="button" value="Search files" class="file_input_button" />
  <input type="file" class="file_input_hidden" onchange="javascript: document.getElementById('fileName').value = this.value" />
</div>
And… voilá. It should be working. I’ve tested it in Firefox 3, IE6, IE7, IE8, Opera 10, Chrome 3 and it worked perfectly in all of them.

The complete solution
So, here is the complete code (css and html all in one):
//css
.file_input_textbox
{
 float: left
}

.file_input_div
{
 position: relative; 
 width: 100px; 
 height: 23px; 
 overflow: hidden;
}

.file_input_button
{
 width: 100px; 
 position: absolute; 
 top: 0px;
 background-color: #33BB00;
 color: #FFFFFF;
 border-style: solid;
}

.file_input_hidden
{
 font-size: 45px; 
 position: absolute; 
 right: 0px; 
 top: 0px; 
 opacity: 0; 
 
 filter: alpha(opacity=0); 
 -ms-filter: "alpha(opacity=0)"; 
 -khtml-opacity: 0; 
 -moz-opacity: 0;
}

 
//html
<input type="text" id="fileName" class="file_input_textbox" readonly="readonly">
 
<div class="file_input_div">
  <input type="button" value="Search files" class="file_input_button" />
  <input type="file" class="file_input_hidden" onchange="javascript: document.getElementById('fileName').value = this.value" />
</div>
There. I hope it works for you as well as it did for me. If you find it doesn't work that well, feel free to let me know.

And if you like playing android games, why not check my new game "Up Up n' Roll Away" in the Play Store:
https://play.google.com/store/apps/details?id=com.BubbleBoy.UpUpRollAway


Friday, January 15, 2010

Best Practices for Web Forms Design

Here’s a great document by Luke Wroblewski concerning Web Forms Design theory:

http://www.lukew.com/resources/articles/WebForms_LukeW.pdf

Ever wondered if you should right or left align your fields’ labels? If you should put your labels on top of the fields, etc? It’s all there with lots of screen shots.