Nowadays, every web project is expected to look appealing and beautiful. To achieve this, web developers use a lot of CSS and JavaScript to generate beautiful and useful user interfaces.
Sometimes getting a small element to look nice and consistent across browsers and platforms looks more challenging than it really is. Let’s imagine that you want to create a custom file input that will look like the one below:

When you type <input type=”file” />
in your HTML file, you will be quickly disappointed with the default result that will look something this:

You will not be able to achieve the result you want if you try to style the file input directly. Each web browser renders the file inputs its own way, and no two browsers will display it in the same way. Not to mention that the default browser rendering looks unattractive. There are many ways to render an HTML file input so it looks and behaves consistently across all browsers. There are even plugins to help you get the job done. But our best CSS Toptal developers have a simple and elegant way to customize file inputs using just CSS and a little touch of JavaScript help.
The first thing you need to do is create the HTML markup by putting the file input into another tag. We will use a span tag in this example, but you can use any tag you want:
<span class="file-input">
Browse<input type="file" />
</span>
The result of the code above is as follows:

Now we are going to hide the file input but keep it clickable. When users click on the Browse
text, they will actually be clicking on the hidden file input. To do so, we have to add the CSS below:
.file-input {
position: relative;
overflow: hidden;
}
.file-input input[type="file"] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
outline: none;
display: block;
cursor: pointer;
}
What the code above does:
- The
span
.file-input
is positioned relatively so its children could be positioned absolutely if we want.
- The file input is positioned absolutely to stay over the
Browse
text. We also set its opacity to 0 so it won’t be visible. The cursor: pointer will show the users that they can click it.
After applying this CSS, the result will be:

You can notice that the Browse
text is clickable and dispatches the file search, as we want.
Now we will just add more style to the .file-input
class so it will turn into a green button:
.file-input {
position: relative;
overflow: hidden;
border: 1px solid #1f7c57;
border-radius: 3px;
background: linear-gradient(#43c692, #39b885);
color: white;
padding: 5px 10px;
display: inline-block;
font-family: 'Trebuchet MS';
font-weight: bold;
}
The next result is:

Great. It looks like we are done. But we have a little problem: once we click on the button and select a file, no result is shown to the user. This is because the file input is hidden, so the users can’t see the file name that is selected. A little JavaScript function will help us to solve this problem. We will add an empty tag <span class="filename"></span>
and use it to show the file name once the file is selected.
By adding the style below to the span
.filename
, it will make it prettier:
.filename {
font-family: 'Trebuchet MS';
padding: 5px 10px;
display: inline-block;
vertical-align: top;
font-style: italic;
}
Now we are going to add a function that listens to the file input changes and fills out the span
.filename
. The example below is using jQuery, but we can also do it by just using a pure vanilla JavaScript:
<script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
$(document).ready( function() {
$('.file-input input[type="file"]').change( function() {
var filename = $(this).val().replace(/\\/g, '/').replace(/.*\//, '');
$('.filename').html( filename );
});
});
</script>
Now our code is ready. When a user selects a file, the file name will be placed into the span
.filename
.

You can download the example code on GitHub.