-
Rediscover the HTML select element
Learn how to unlock full control of styling select menus on the web. The HTML select element is getting a major upgrade with a new CSS appearance value, and new pseudo-elements. Discover how the select options can contain rich content with new possibilities in HTML. Build selects that match your design system, while keeping all the accessibility and robustness of the default element.
Chapters
- 0:00 - Introduction
- 2:32 - Style the select button
- 3:47 - Customize the drop-down
- 5:00 - Go beyond text options
- 6:50 - The selectedcontent element
- 7:46 - Fallback for unsupported browsers
- 8:49 - Next steps
Resources
- WebKit.org - Example website demonstrating Customizable Select
- WebKit.org - CSS Grid Lanes Field Guide
- WebKit.org – Report issues to the WebKit open-source project
- Submit feedback
Related Videos
WWDC26
-
Search this video…
Hi! I'm Tim, a Safari Engineer. Today, I'm going to take you through a new way to use the select element that makes it completely customizable, while still reusing the power of semantic HTML.
As a web developer, you've probably wrestled with drop-downs. Going beyond the default select element meant using heavy JavaScript libraries or lots of div elements. Accessibility can also get tricky to handle. Now, there's an easier way, all using just HTML and CSS: Customizable select. Starting in Safari 27 and Chrome 135, you can use the pre-existing select element to seamlessly integrate your drop-downs into your website.
To see how it works, I'm going to implement customizable select on a website I'm building for a client.
I've been working with a photographer to build their portfolio so they can showcase and sell their photos. My client wants some sorting and filtering options, for which I'll use the select element.
And yes, my client is also named Tim.
As a reminder, this is the HTML markup for the select element with its label.
The select element is a powerful tool, giving us basic accessibility right out of the box.
I'm able to use the keyboard to navigate option elements and it works well with screen readers, all without needing any external libraries. I'll use that to build the Sort by button on my page. This is the native select, which by the way, are called pull down buttons on Apple platforms.
What's great about the native select is it matches every other control on the platform, giving users a familiar way to navigate them.
But when I place my form control on my photo site, it feels a little out of place. It doesn't quite blend into the style of my site the way I want.
This is where customizable select comes in. I'll take you through the different steps of customization so that I get a select that better matches my design. I'll start by styling the select buttons on my site. The button is the part of the select element that I can click to show the select menu. Then, I'll use customizable select to style that menu, which displays my options.
Finally, I'll show you how you can break away from the classic select element layouts with content that goes beyond just text.
Let's go back to our first item, I'm going to style the most basic part of the control, the button.
Starting from scratch, I get the native control. But now, I can use the new customizable select appearance to get a smaller set of styles to change to match my site's design. The first step is to apply — appearance: base-select.
Since I previously set up font-family: Gill Sans on the body element, the body font is now inherited by the select button, matching the label beside it.
That's already bringing me one step closer to matching the design of my site. As a next step, I'll adjust the background, border, and padding. I like how well it matches my site. One last detail I want to change is the arrow. With customizable select, I can use a new selector called ::picker-icon to change it. I'll use the ::picker-icon selector to set the content property to a new glyph and to size it correctly with a width. Using the:open pseudo-class, I can also set different colors on the button when the drop-down menu is open.
I've also updated the arrow to match the text color for the open state.
Here is my select, matching the rest of my site. And that took me only a few lines of CSS to write. Now, I want to style the drop-down itself, and customizable select lets me do this! I'll show you how. Like ::picker-icon, the drop-down menu also comes with styleable parts: the menu itself can be styled with ::picker(select) on the select element and the check with ::checkmark on the option element.
Now let's add some CSS. To start with a clean slate, I need to first opt-out of the native menu. I can do that by using the new ::picker(select) selector, and by setting appearance: base-select. Now, I'm ready to go. First, I'm going to arrange my spacing with some padding and margin. Let's handle the borders and the box-shadow on my drop-down.
Perfect! Now I want to put some emphasis on the selected option so it's clear to my customer what they've picked. I can set a bold font on the checked option and gray out the other ones.
As a final step, I'll change the default checkmark by setting the content CSS property and the width on the ::checkmark selector, similarly to what I did with ::picker-icon.
It's amazing how far I was able to go styling my Sort by menu with so little code.
How much further can I go? With customizable select, I can now go beyond the simple list of options displayed as text. I'll go through an example with my next feature. My client is best known for photography in a handful of categories and I want to spotlight those photos. So, I'll add a way to browse photographs by their most popular categories. I decide to create another select element using the previous styling. However, I want the select to have symbols to make it more visually interesting.
With customizable select, I can put any kind of content: images, videos, emojis, whatever I like.
In this case, I've chosen to use an SVG and a label inside each option element so the customer can explore the categories more easily.
I left the image alt text empty because I don't want the "Flowers" label to be called out twice on screen readers. Since I removed the checkmark, I want to highlight the selected option more prominently. I'll use the checked selector to change the colors.
This works, but my layout doesn't really fit my window.
The symbols make the drop-down very long. I need to try something else. With customizable select, it's simpler than ever to bring different layouts to the select drop-down, while reusing the power of other CSS features in my drop-down. Here, I've gone with a grid layout.
Grid-template defines the number of rows and columns, while gap defines the spacing between the grid cells. That puts my drop-down in a nice grid. I think this looks much more organized. I've finished my drop-down, but I realize I now want to have the SVG of the selected option inside the button itself. My symbols were already in the HTML markup, so why aren't they in the button? I need to do one more thing for this to happen. Select comes with a button. That's what people click to open the drop-down. But that button only displays text.
My image is rich content.
I'm going to use another tool that I get from customizable select to solve that problem: the element.
Customizable select now lets me replace the built-in button by placing a button element as the first child of the select element. Since my button is currently empty, I only see the arrow.
Putting a button in a select element was previously not allowed in HTML, now it lets me put custom content inside the button, like labels or like the new element. What's special about is that it shows the rich content that's part of my selected option, like my SVG that's next to the "Everything" label.
I think Tim is really going to like how this menu looks and works, but I'm not quite done yet. I need to check how this looks in browsers that don't support customizable select.
Here's where progressive enhancement kicks in - it's still usable in browsers that don't support the feature.
Customers get the native pop-up. This is one of the things that are great about re-using the select element. And because it is a semantic element, I still get those built-in accessibility features.
This was exciting! My select elements blend in nicely with the look and feel of the site. I even added a fun radial color picker, also built entirely with customizable select. Now, my client has a beautiful, sortable home for their photographs. I also got to take advantage of Safari's support for Grid Lanes to lay out my images.
To learn more, check out "Learn CSS Grid Lanes" where Brandon shows you how this new layout method works.
These features are coming to Safari 27. If you want to try them now, you can download Safari Technology Preview or Safari Beta.
Be sure to check out the demo on webkit.org, and try styling something simple with customizable select on your own website.
Make sure to test your select with browsers that don't support the technology and with assistive tools. Webkit.org has a blog post to learn more about best practices to help make your interface work for everyone.
Finally, get creative and try experimenting with different ways to implement it. Most importantly, I hope you have fun! I can't wait to see how you use this feature on your website. Thanks for watching!
-
-
1:11 - Basic markup
<label for="sort-select">Sort by</label> <select id="sort-select"> <option>Newest</option> <option>Oldest</option> </select> -
2:37 - Native form control
select { } -
2:50 - appearance: base-select
body { font-family: Gill Sans, sans-serif; } select { appearance: base-select; } -
3:07 - Style the select button
select { appearance: base-select; background-color: var(--green-10); border: none; padding: 0.6em 1em; } -
3:08 - Picker icon
select:open { background-color: var(--green-100); color: white; } -
3:29 - Picker icon open state
select:open { background-color: var(--green-100); color: white; } select:open::picker-icon { content: url(icons/arrow-white.svg); } -
4:08 - Picker select
::picker(select) { } -
4:21 - Picker select spacing
::picker(select) { appearance: base-select; padding: 4px; margin-top: 0.5em; } -
4:28 - Picker select border and shadow
::picker(select) { appearance: base-select; padding: 4px; margin-top: 0.5em; border: 1px solid rgba(0,0,0,0.2); border-radius: 9px; box-shadow: 0 4px 20px rgba(0,0,0,0.2); } -
4:36 - Custom option styles
option:checked { font-weight: 600; } option:not(:checked) { color: #777; } -
4:42 - Picker option checkmark
option::checkmark { content: url(checkmark.svg); width: 0.65em; } -
5:31 - Images in option
<option value="flower"> <img src="flowers.svg" alt=""> <span class="text">Flowers</span> </option> -
5:52 - Custom option highlight
option::checkmark { display: none; } option:checked { background: #00857e; color: white; } -
6:20 - Grid layout in drop downs
::picker(select) { display: grid; grid-template: 1fr 1fr / 1fr 1fr 1fr; gap: 1rem; } -
6:43 - Select with image options
<select> <option value="anywhere"> <img src="icons/all.svg" alt=""> <span class="text">Everything</span> </option> <option value="buildings"> <img src="icons/buildings.svg" alt=""> <span class="text">Buildings</span> </option> <option value="flowers"> <img src="icons/flower.svg" alt=""> <span class="text">Flowers</span> </option> </select> -
7:11 - Select menu
<select> <option> </option> <option> </option> <option> </option> </select> -
7:13 - Select menu button
<select> <button> </button> <option> </option> <option> </option> <option> </option> </select> -
7:29 - SelectedContent Element
<select> <button> <selectedcontent></selectedcontent> </button> <option> </option> <option> </option> <option> </option> </select>
-
-
- 0:00 - Introduction
Introducing Customizable Select, a way to fully style the HTML Select Element in CSS while keeping its built-in accessibility, available in Safari 27 and Chrome 135. Follow along as a "Sort by" menu and a category picker are built to fit right into a photographer's portfolio site.
- 2:32 - Style the select button
Apply `appearance: base-select` to opt into the new styling model, then customize the button with familiar CSS — fonts, background, border, and padding. Use the new `::picker-icon` pseudo-element to swap the dropdown arrow, and the `:open` pseudo-class to change colors when the menu is showing.
- 3:47 - Customize the drop-down
Style the menu itself by applying `appearance: base-select` to the `::picker(select)` pseudo-element. Adjust spacing, borders, and box-shadow, emphasize the active option with the `:checked` pseudo-class, and replace the default checkmark using `::checkmark`.
- 5:00 - Go beyond text options
Place rich content like SVG icons, images, or labels directly inside
- 6:50 - The selectedcontent element
Replace the built-in select button by placing a
- 7:46 - Fallback for unsupported browsers
Browsers that don't support customizable select fall back to the native popup automatically — progressive enhancement just works because you're still using a semantic
- 8:49 - Next steps
Try the demo on webkit.org, experiment with customizable select in your own projects, and test against assistive tools and non-supporting browsers. To see the Grid Lanes layout used to display the photos, watch "Learn CSS Grid Lanes."