::file-selector-button

Avatar of Sunkanmi Fafowora
Sunkanmi Fafowora on (Updated on )

DigitalOcean joining forces with CSS-Tricks! Special welcome offer: get $200 of free credit.

The ::file-selector-button in CSS is a pseudo-element that selects <input type="file"> in HTML.

input::file-selector-button {
  background-color: #f8a100;
}

You’ve undoubtedly come across file upload inputs — they’re very common, especially for including file attachments in a form, like a PDF or image.

Syntax

selector::file-selector-button { }

You actually don’t have to specify element in front of the pseudo-element:

/* This works */
input[type="file"]::file-selector-button{ }

/* But this is more concise */
::file-selector-button{ }

Of course, that will style all file selector buttons globally. If you are trying to target one instance of a file selector button, then you will want to include a selector matches it.

Compatible CSS properties

::file-selector-button works with any valid CSS property.

Specification

The ::file-selector-button is defined in the CSS Pseudo-Elements Module Level 4 specification. (Here is the original ticket for it.)

The button is part of the shadow DOM

The file input button is located in the shadow DOM. Like an <iframe>, selectors and styles inside a shadow DOM node don’t leak outside of the shadow root. Likewise, styles from outside the shadow root don’t leak in.

Showing the file input button in the source code of the DevTools inspector.

That applies to file input buttons too. ::file-selector-button gives us limited access to style the button. It’s limited because there’s no way to style the placeholder “no file selected” text beside the button. Notice, too, that the text is unselectable.

One more thing to note about the shadow DOM here is that styling the file input button in web components — which embed elements in a shadow DOM node — fails since the encapsulated styles are unable to leak out of the component and into another shadow DOM node, as explained by Hayato Ito.

Animations are a no go

Although the official doc says:

There is no restriction on which properties apply to the ::file-selector-button pseudo-element.

…I have found the pseudo-element cannot be animated. Perhaps it has less to do with the animation property and more to do with @keyframes being incompatible? Either way, I filed an issue that you can track in case there’s progress on this front.

Demo

I came across a CodePen demo with neat hover effects for buttons that use box shadows to fill the button’s background color and thought I’d apply it to a file input to demonstrate what’s possible with ::file-selector-button:

Browser support

IEEdgeFirefoxChromeSafariOpera
10-1189828914.175
iOS SafariAndroid ChromeAndroid FirefoxAndroid BrowserOpera Mobile
14.510410110464
Source: caniuse

Earlier versions of Safari, Chrome, and Opera used a prefixed version of the pseudo-selector, ::-webkit-file-upload-button. Similarly, older versions of Edge and Internet Explorer relied on ::-ms-browse. So, if you’re looking for a solid way to ensure maximum browser support, here’s your recipe:

/* Fallback for Safari, Chrome, and Opera */
input[type="file"]::-webkit-file-upload-button {
  background-color: #f8a100;
}
/* Fallback for Legacy Edge and IE */
input[type="file"]::-ms-browse {
  background-color: #f8a100;
}
/* Standard */
input[type="file"]::file-selector-button {
  background-color: #f8a100;
}