There are numerous ways to customize the HTML file input element to look it better. In this post, let’s customize the design and behaviour of the HTML file input in a more attractive way using JavaScript and CSS only so that it has an impact on the overall user experience.
HTML
We are going to use one <svg></svg>
element to show an icon and one <span></span>
to show selection text inside a <label></label>
along with <input type='file'/>
to design the HTML file input . So the label is the container for SVG icon and span text. This is how our HTML code looks like:
<input type="file" name="file-1[]" id="file-1" class="inputfile inputfile-1" data-multiple-caption="{count} files selected" multiple />
<label for="file-1">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17">
<path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z" />
</svg>
<span>Choose a file...</span>
</label>
CSS
We are going to hide the <input type='file'/>
by setting the opacity to zero. We will design the next sibling of that HTML file input which is a label. For that purpose, we will create a CSS class named inputFile
. Then we will add necessary styles to its next sibling.
.inputfile {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.inputfile + label {
max-width: 80%;
font-size: 1.25rem;
font-weight: 700;
text-overflow: ellipsis;
white-space: nowrap;
cursor: pointer;
display: inline-block;
overflow: hidden;
padding: 0.625rem 1.25rem;
}
.inputfile:focus + label,
.inputfile.has-focus + label {
outline: 1px dotted #000;
outline: -webkit-focus-ring-color auto 5px;
}
READ: How to Create Icon Input Element Using HTML and CSS
JavaScript
var inputs = document.querySelectorAll('.inputfile');
Array.prototype.forEach.call(inputs, (input) => {
var label = input.nextElementSibling, labelVal = label.innerHTML;
input.addEventListener('change', (e) => {
var fileName = '';
if (this.files && this.files.length > 1)
fileName = (this.getAttribute('data-multiple-caption') || '').replace('{count}', this.files.length);
else
fileName = e.target.value.split('\\').pop();
if (fileName)
label.querySelector('span').innerHTML = fileName;
else
label.innerHTML = labelVal;
});
});
So final output will be:

You can find the complete repository on Github. There are a whole bunch of example designs of the input HTML element for practice.
Final Thoughts
This input HTML element might be a very small part of the user experience, but when you do nurture small parts of your whole UI elements to improve their design and behaviour, it would definitely have an impact on your overall user experience. So while developing an application everyone should keep an eye on such details.