Warning the following is just a quick idea of how to achieve this by styling the actual input and visually hiding the label (to ensure it is still accessible).
However there are lots of accessibility issues you still need to consider, showing which file was selected for example.
But this does show you how you can style the input to keep all the native functionality without having to re implement it yourself (active state for example, which I styled here). Also don't forget a custom focus indicator, input:focus::before
.
There are other issues such as browser support to consider as well, however in theory this should fall back reasonably gracefully, I just haven't tested it.
This codepen gives a good starting point on how to implement some of the features this is missing such as showing the file name selected.
input{
color: transparent;
width:150px;
height:28px
}
input::-webkit-file-upload-button {
visibility: hidden;
}
input::before {
content: 'Select a PDF';
color: black;
display: inline-block;
border: 1px solid #999;
border-radius: 3px;
padding: 5px 8px;
outline: none;
white-space: nowrap;
-webkit-user-select: none;
cursor: pointer;
text-shadow: 1px 1px #fff;
font-weight: 700;
font-size: 10pt;
width:132px;
}
input:hover::before {
border-color: black;
}
input:active {
outline: 0;
}
label {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
clip: rect(1px, 1px, 1px, 1px);
white-space: nowrap; /* added line */
}
<input id="input" class="input" name="newFile" type="file" accept=".pdf" data-required="true"/>
<label for="input">upload file</label>