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.](png/s_8b4a1e94f5819114a6727ab5c66fb79222bf10ce84ce9a9026b57b6ec0e3f806_1661376504083_screenshot2022-08-24at2.11.50pm4738.png)
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
IE | Edge | Firefox | Chrome | Safari | Opera |
---|---|---|---|---|---|
10-11 | 89 | 82 | 89 | 14.1 | 75 |
iOS Safari | Android Chrome | Android Firefox | Android Browser | Opera Mobile |
---|---|---|---|---|
14.5 | 104 | 101 | 104 | 64 |
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;
}