For years the answer to "can I style a <select>?" was "no, build your own out of
<div>s." So everyone did, and most of those homemade dropdowns were quietly
broken for keyboard and screen-reader users. Now there's a real fix: opt a native
<select> into the styleable model with appearance: base-select, and you unlock
the ::picker(select) pseudo-element, the selectedcontent element, and full
control over the internals of each <option> — icons, swatches, avatars, the lot.
This is genuinely good. It's also the most seductive accessibility trap CSS has
shipped in a while.
Here's the mechanism of the trap. The moment you can put arbitrary markup inside an
<option>, the temptation is to make the option be the visual — a flag, a color
chip, a product thumbnail — because that's what the design comp shows. Do that, and
you can ship a dropdown that looks immaculate and exposes an empty accessibility
tree. It looks done. It demos well. It's hollow.
WebKit's golden rule of customizable select
is, in their words, "single but essential": always provide text content or
accessible text attributes for your option elements. Or put more bluntly: icons,
swatches, and illustrations are additions to an option, never substitutes for it.
That framing is the whole point. It reads like a feature announcement but it's
really a warning — the prettier each option gets, the easier the regression is to
miss, because nothing on screen tells you the text is gone.
The practical pattern is small. Keep real text in the DOM even when you're only
showing a visual: a .visually-hidden span carries the label for assistive tech
while the icon does the looking. An <img> standing in for an option needs an
alt (or aria-label) that is the label; alt="" is correct only when the
image is purely decorative and a visible text label already exists.
And wrap the whole enhancement in a support query so the floor never drops out:
@supports (appearance: base-select) {
select, ::picker(select) { appearance: base-select; }
}
As of 2026 this is firmly progressive-enhancement territory. Chromium shipped
appearance: base-select first (Chrome 135,
March 2025); other engines are at various stages, with Firefox still behind a flag
at the time of writing. So feature-detect, don't version-check — and let
non-supporting browsers fall back to a plain native <select>. Which works out
fine, because the fallback only behaves if your options carried real labels all
along. Same rule, top to bottom: the text is the product. The pixels are the
garnish.