@Ever answer is better because it doesn't use javascript, but it has some issues as @Shanika said. To function we have to click on the button text, not the button. So I guess we can wrap it all with a label element. But it doesn't work yet. Next, we can wrap the button element with a div element and add pointer-events:none.
<label for="fileUpload">
<input type="file" id="fileUpload" style="display:none;" />
<div>
<input type="button" value="Upload" style="pointer-events:none;" />
</div>
</label>
EDIT:
@AgainPsychoX, We can use a custom style for the button if it is possible
button {
all: unset;
label {
padding: 2px 6px;
border: 1px solid gray;
border-radius: 3px;
background-color: #f0f0f0;
font-family: Arial;
font-size: 13.5px;
}
&:hover,
&:focus-within {
label {
border: 1px solid #4b4b4b;
background-color: #e5e5e5;
}
}
}
<button>
<label for="fileUpload2">Upload</label>
</button>
<input type="file" id="fileUpload2" style="display: none" />
@Animal Rights, I think we can't go ahead with this approach if we want to use keyboard.