02UI

File upload

A file upload lets someone choose a file from their device or drop one onto a target zone. The chosen file name, size and progress are part of the control.

Forms and inputBuild difficulty: Hard<input type="file">

Also called Drop zone, File picker, Attachment.

Drop a PDF or image here, or browse

Up to 10 MB

No file chosen yet.

Drop a file onto the zone, or click Choose file. The name of the selected file appears below. Tab to the button and press Enter to open the picker.

For designers

File upload is the bridge between your form and someone's disk. Dropbox, expense apps and job applications all need a clear place to put a PDF or photo, then confirmation that the right file was chosen.

The cost is failure modes. Wrong type, file too large, upload interrupted and mobile browsers that handle cameras differently all need copy and recovery. A plain button that opens the picker is enough for a single optional attachment. A marked drop zone earns its space when files are the main action on the screen.

State the limits before someone picks. Max size and accepted types belong in helper text under the zone, not only in an error after upload fails. Ten megabytes and PDF or image sets expectations early.

When to use a file upload

Use a file upload when

  • Someone must attach a document, image or other file from their device
  • Drag and drop onto a marked area is faster than hunting through folders
  • You need to show the file name and upload progress before submit

Reach for something else when

Variants

Attach invoice

PDF only

Uploaded

  • receipt-march.pdfDone
  • scan-02.pngUploading…

A compact row for one attachment in a form, and a multi-file list after upload.

Drop zone. A dashed border and short instruction text. The whole area opens the picker on click.

Button only. A compact Upload or Attach button in a form row. Fits when the file is secondary to other fields.

With file list. After select, show each file as a row with name, size, progress and remove.

How to build a file upload

Use a native file input. Hide it visually if you want a custom button or drop zone, but keep it in the DOM and associate it with a label.

<label for="receipt">Receipt</label>
<div
  role="button"
  tabindex="0"
  aria-controls="receipt"
  aria-label="Drop a file or browse"
>
  Drop a PDF or image here
</div>
<input
  id="receipt"
  type="file"
  name="receipt"
  accept=".pdf,image/*"
  hidden
/>
<button type="button">Choose file</button>
<p aria-live="polite">No file chosen</p>

Clicking the zone or button triggers input.click(). On change, read files[0] and update the live region with the name. For drag and drop, call preventDefault on dragover and read dataTransfer.files on drop. Keyboard users need Enter or Space on the zone to open the picker.

The file name after select is part of the design. Show it in plain text with size in kilobytes or megabytes. Offer Remove before submit so someone can fix a wrong pick without refreshing the page.

Edge cases

No file selected on submit. Block submit with a field-level error, or treat the field as optional and say so in the label.

Replacing a file. Let someone pick again and overwrite the previous selection, or remove first then add.

Security. Never trust the client extension alone. Validate type and size on the server.

Camera on mobile. The same input can open the camera when accept includes image/* and capture is set. Test on iOS and Android because the picker order differs.

Virus scanning. Enterprise flows sometimes scan after upload. Show Scanning beside the file name, then Done or a quarantine message. People should know the file arrived even when it is not yet available.

Common questions

Drop zone or button only?
Offer both when space allows. The zone invites drag and drop. The button reaches keyboard users and anyone who prefers the system file picker. One hidden input can serve both.
What should accept contain?
List the MIME types or extensions you truly support, like image/png or .pdf. Broad accept values set false expectations when the server rejects the file.
How do I show upload progress?
After select, show the file name and a progress bar or percentage while the upload runs. Replace the bar with a done state or an error with a retry action.
Can people upload more than one file?
Add the multiple attribute when the backend accepts several files. Show each file as its own row with its own remove control.
Is drag and drop accessible?
Drop zones still need a keyboard path. Click or Enter on the zone should open the same file picker as the button. Do not rely on drag alone.
What happens when a file is too large?
Check size before upload when you can. Show a clear message with the limit in megabytes. Do not start the upload and fail halfway.

Last reviewed 27 AUG 2026