How to style a file input
Short answer
The ::file-selector-button pseudo-element styles the button inside the field:
<style>
input[type="file"]::file-selector-button { margin-right: 12px; padding: 8px 16px; border: 0; border-radius: 8px; background: steelblue; color: white; font: inherit; cursor: pointer; }
input[type="file"]::file-selector-button:hover { background: navy; }
</style>
<input type="file">The text next to the button ("No file chosen") is written by the browser, and its styles are set on the <input> itself.
Which files to accept
accept limits the choice to the needed types, and multiple allows selecting several files at once:
<label>Photos: <input type="file" accept="image/*" multiple></label>The limit only works in the file dialog. The server must still check what it received.
A custom button via label
If the field must look completely different, hide it visually and turn a <label> into the button: a click on the label opens the file dialog.
<style>
.upload input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.upload span { display: inline-block; padding: 10px 18px; border: 2px dashed steelblue; border-radius: 8px; cursor: pointer; }
.upload input:focus-visible + span { outline: 2px solid orange; }
</style>
<label class="upload"><input type="file"><span>📎 Attach a file</span></label>Common mistake
The field is hidden with display: none or hidden. The label button works with the mouse, but the keyboard cannot reach it: a field hidden this way drops out of the Tab order. Hide the field visually, as in the example above.