Get affordable and hassle-free WordPress hosting plans with Cloudways — start your free trial today.
Experimental: Check browser support before using this in production.
The ::picker()
pseudo-element targets and styles a form element’s open menu of options. This is currently supported only by the <select>
element, but it may be supported by other elements in the future, such as <input type="color">
.

In CSS, we would style the picker menu like this:
/* Required to "reset" the element's appearance for customization */
select,
select::picker(select) {
appearance: base;
}
::picker(select) {
border: 3px solid oklch(65% 0.2 300);
background: oklch(98% 0 0);
color: oklch(20% 0.05 300);
}
The ::picker()
pseudo-element is defined in the CSS Form Control Styling Level 1.
Syntax
The official definition from the specification says this:
::picker( <form-control-identifier>+ )
<form-control-identifier> = <select>
In plain English? It’s saying we use ::picker
as the selector and tell it exactly what kind of picker (<form-control-identifer>
) it’s selecting. By default, the <select>
element is the kind of picker.
Arguments
/* Picker set to a select element */
::picker(select) {
background: lightblue;
}
/* We still have to set "select" event if it's used as the selector */
select::picker(select) {
background: purple;
}
There are two conditions for ::picker()
to work:
- The element supports some kind of “picker” like a drop-down menu of
<option>
elements. - The element’s picker supports
appearance
and is set tobase-select
is that the default appearance is wiped out and ready for custom styles.
To use it, we would need to declare select
as the type of picker we’re customizing:
select,
::picker(select) {
/* Styles go here. */
}
Then we reset the picker’s appearance to set it up for custom styles:
select,
::picker(select) {
appearance: base-select;
}
Heads-up: This cannot be applied to another pseudo-element, such as ::after
or ::before
. In other words, this pseudo-element does not support other pseudo-elements, which is also true of any pseudo-element.
select
s?
Why declare two I’m sure you’re wondering why ::picker()
accepts select
as an argument, the same way :is()
and :has()
do. A more intriguing question: why can we write select twice, like this?
/* Declare the <select> element */
select,
/* Declare it again as an argument */
::picker(select) { }
That’s because we might be working with more than a <select>
menu in the future, like <input type="color">
or <input type="date">
. That means we have to be specific about what type of picker we’re selecting. Otherwise, the selector would select all types elements with pickers. So, even if it currently only supports <select>
, being specific about it now is a good way to future-proof your work while additional support is in the works.
That said, you can simply write ::picker(select)
instead of select::picker(select)
. Both ways work and are provided here merely for demonstration.
Basic usage
Basic CSS styling can be added to this, so feel free to play around with it in the following demo.
::picker(select) {
background-color: coral;
color: crimson;
font-family: sans-serif;
}
The demo above randomly changes the <select>
‘s ::picker
styles, showing how we can creative we can be with the picker’s font, font color, and background color.
It is an anchor element
What’s more interesting is that the picker pseudo-element is actually an anchor element attached to the <select>
element! This means we can move it around using CSS Anchor Positioning.
In the demo below, we set the picker at the top-right position, overriding the default style that sets it below the <select>
:
Well, not just the position, but other values like its min-block-size
. The specification says we can customize any of the picker’s following properties:
inset: auto;
margin: 0;
min-inline-size: anchor-size(self-inline);
min-block-size: 1lh;
max-block-size: stretch;
overflow: auto;
position-area: block-end span-inline-end;
Heads up! You override other properties, even though they are not explicitly noted in the specification. You saw earlier how we were able to style the picker’s font-family
, color
, and background-color
in a previous demo, for example.
::picker()
Animated menus with Normally, we are unable to animate a dropdown menu popping in and out. But with ::picker()
, we can animate the menu opening when we define a @starting-style
for it:
::picker(select) {
transition: all 0.5s;
}
:open::picker(select) {
height: 9rem;
opacity: 1;
@starting-style {
opacity: 0;
height: 0;
}
}
If your browser supports it, you will see the picker animate upward when it is opened.
Here’s a video showing that, just in case:
We can button things up a little nicer by setting the ::picker()
‘s transition-behaviour
to allow-discrete
so it closes as smoothly as it opens:
::picker(select) {
transition-behavior: allow-discrete;
}
Demo
Here’s a simple demo with ::picker()
animated and styled. If your browser does not support it yet, then it gracefully falls back to a default picker experience.
Specification
The CSS ::picker()
pseudo-element is defined in the CSS Form Control Styling Level 1, which is currently in Editor’s Draft status. That means the information can change between now and when it officially becomes a Candidate Recommendation.
Browser support
Chrome | Edge | Firefox | Safari |
---|---|---|---|
115 | 115 | 111 | No |