How to Style File Inputs with ::file-selector-button

Styling native file upload buttons has historically required complex hacks involving hidden inputs and custom labels. The CSS ::file-selector-button pseudo-element solves this by allowing developers to style the button inside an <input type="file"> directly using standard CSS properties. This guide covers how the pseudo-element works, standard implementation methods, state handling, and browser compatibility.

What Is ::file-selector-button?

When you render an <input type="file"> element, browsers generate a compound UI component containing two main parts: a button (typically labeled "Choose File" or "Browse...") and a text label indicating the selected file name or "No file chosen."

The ::file-selector-button pseudo-element specifically targets and isolates that internal button, leaving the accompanying text label untouched.

Basic Implementation

You can apply standard box model, typography, and color properties to ::file-selector-button just like a regular <button> element.

input[type="file"]::file-selector-button {
  background-color: #0284c7;
  color: #ffffff;
  border: none;
  border-radius: 4px;
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  margin-right: 12px;
  transition: background-color 0.2s ease-in-out;
}

This replaces the operating system's default button appearance with your custom styles while preserving the native file-picker functionality.

Adding Interactive States

Interactive pseudo-classes such as :hover, :active, and :focus chain directly with ::file-selector-button to provide user feedback.

input[type="file"]::file-selector-button:hover {
  background-color: #0369a1;
}

input[type="file"]::file-selector-button:active {
  background-color: #075985;
}

When handling disabled states, style the button based on the input's :disabled condition:

input[type="file"]:disabled::file-selector-button {
  background-color: #cbd5e1;
  color: #64748b;
  cursor: not-allowed;
}

Styling the Remaining File Text

The ::file-selector-button only affects the button portion. To style the "No file chosen" text or selected filename, apply styles directly to the parent input selector:

input[type="file"] {
  font-family: sans-serif;
  font-size: 14px;
  color: #475569;
}

Browser Support and Legacy Prefixes

The ::file-selector-button is part of the CSS Pseudo-Elements Module Level 4 and enjoys universal support across all modern evergreen browsers (Chrome 89+, Edge 89+, Firefox 82+, and Safari 14.1+).

Prior to standardization, browsers implemented their own vendor-prefixed pseudo-elements:

  • WebKit/Blink: ::-webkit-file-upload-button
  • Gecko: ::-moz-range-thumb (for ranges) or custom shadow DOM components
  • Internet Explorer/Edge (Legacy): ::-ms-browse

For modern web development, vendor prefixes are no longer necessary unless you must support legacy versions of Safari or Internet Explorer. Writing standard ::file-selector-button declarations is sufficient for cross-browser styling.