Encodera

Thanks for reading!

Donate to the site — we work hard for you.

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.

Functions used in this recipe

  • <input> — An input field; its kind is set by the `type` attribute.
  • <label> — A label for a form field.
  • <button> — A button: submits a form or triggers an action.
  • cursor — The look of the mouse pointer over the element.

Thanks for reading!

Donate to the site — we work hard for you.