How to style file input fields

Mar 18, 2014
CSS
107 Shares
By

One area we always have some difficulty when it comes to styling is input fields and in particular the file input. This type of input doesn’t usually allow for much customization but with some JavaScript tricks we can create our own file input that matches our website’s look and feel.

 

The HTML

Using the default HTML element for file input we can’t create much so in this article we will create our file input that will be hidden and we will create another button that with some javascript magic will behave like the file input and with a click it will pop us up the file dialog:

<input type="file" id="file>
<button id="select">Select some files</button>
<span class="name"></span>

As you can see we also have a span with the class of name, this span will contain the name of the file we select so we can also style that as we wish.

Before we move on to the JavaScript code we need some simple CSS in order to make the input disappear but still be active through JavaScript and for that we need to set its visibility to hidden and also set its width and height to 0 like so:

#file{
  visibility: hidden;
  width: 0;
  height: 0;
}

We use visibility instead of display because by using display and setting it to none some browsers wouldn’t let us activate that input through JavaScript.

 

The JavaScript

 The first step towards having our custom file input is mimicking a click event on the input when the user is actually clicking on the dummy button and for that we just need to check when the user has clicked the dummy button and when he does we need to hook the .click method to the actual file input. The click method mimics a mouse click on an element so using this bit of JavaScript we can click the dummy button and JavaScript will trick the browser into thinking we are clicking the actual file input.

$('#select').click(function(e) {
  $('#file').click();
});

If you click on our button you will see that the file dialog already pops up but when we select a file nothing happens in the span and for that we need another function that will trigger every time our input changes in some way and when it does we need to store the value of the input (the value is the path to our file) and place that inside the span:

$('#file').change(function() {
  var value = $(this).val();
  $('.name').html(value);
});

If you check this in the browser you can see that it works but one problem it has is that it shows the path to the file and only showing the name of the file would be much nicer. To accomplish this we need to split the value by a backslash and this will return an array of all the strings that are after and before any backslash and since we want the last string in the path we will get the last element in that array and place that in the span. 

$('#file').change(function() {
  var value = $(this).val(),
      path = value.split("\\"),
      file = path[path.length-1];
$('.name').html(file);
});

If you test this on the browser you will see that in the span we now only have the name of the file instead of having the entire path. If you want this this in action you can check this pen I created.

Having all of this done you can customize this file input as you please , in my case I used this CSS to achieve what you see in the demo:

#file {
  visibility: hidden;
  width: 0;
  height: 0;
}
#select {
  width: 150px;
  height: 70px;
  background: #2ecc71;
  border: none;
  color: white;
  font-family: helvetica, arial, sans-serif;
  font-weight: bold;
  font-size: 18px;
  box-shadow: 2px 2px 1px #27ae60;
  border-radius: 5px;
  float: left;
}
#select:hover {
  box-shadow: 1px 1px 1px #27ae60;
}
.name {
  color: #3498db;
  font-family: helvetica, arial, sans-serif;
  font-size: 16px;
  font-weight: bold;
  background: #ecf0f1;
  display: block;
  border-radius: 0px 5px 5px 0px;
  float: left;
  padding: 1px 6px;
  height: 60px;
  width: 200px;
  font-size: 14px;
  padding-top: 10px;
  position: relative;
  z-index: -1;
}

But the styling options are totally up to you now that you have more flexibility on this input type.

Author: Sara Vieira
Sara Vieira is a freelance Web Designer and Developer with a passion for HTML5/CSS3 and jQuery. You can follow her on twitter or check out her website.
  • JohnReindoer

    Have you thoroughly tested this implementation? It’s been a while since I did something like this, but when I last used your method of passing a click event to the file field via JS it didn’t work in some browsers due to safety restrictions.

    We went for a different implementation by setting the opacity of the file field to 0 and having it float above the custom button. The user thinks he’s clicking our custom implementation, but he’s actually clicking an invisible file field.
    The only problem there is that some browsers behave different when changing the width of a file input and require double clicking on the accompanied text whereas only a single click for the button.

    • http://debeterevormgever.nl/ Elco Klingen

      Using a label with a correct ‘for’ attribute should work, as long as the input is “visible” on the page (ie: margin-left: -9999px)

  • http://www.technbuzz.com/ Samiullah Khan

    Make it easier working with file input. Styling is according to some one likings, but hooking a dummy button to file with javascript is definitely new to me.