Why Native Selects Were a Pain

The appearance: base-select CSS property finally lets developers style native select dropdowns without JavaScript libraries — unlocking full theming of the option list, smooth open animations, and preserved accessibility semantics.

Why Native Selects Were a Pain

Why Native Selects Were a Pain

For two decades, styling a native <select> dropdown was one of the most frustrating jobs in frontend development. The browser's user-agent stylesheet locked down almost every part of it — you could nudge colors and borders on the closed button, but the options list itself was an untouchable black box that ignored your fonts, padding, hover states, and icons.

The industry answer was heavy JavaScript: Select2, Choices.js, or hand-rolled headless dropdowns that replaced the native element entirely. That approach worked, but it came with a tax — accessibility regressions, focus traps, keyboard handling you had to rebuild from scratch, and bundle weight for what should be a trivial control.

Enter appearance: base-select

The core of this change is a single CSS property value: appearance: base-select. By opting in, you strip away the restrictive user-agent styles that have locked down the select since the dawn of the web. The element enters what Chrome's documentation calls its "base" state — a configurable, styleable widget with usable native defaults.

select {
  appearance: base-select;
}

The crucial difference from appearance: none: that older value made radio buttons and checkboxes visually disappear, forcing you to rebuild everything. The new base-select value keeps the widget primitive — usable and interoperable out of the box — while enabling a good degree of customization via CSS.

What You Can Actually Style Now

With base select enabled, the dropdown opens up to modern CSS. The closed button behaves like any other form control: you can set height, padding, border-radius, background gradients, and custom arrows with ::after. More importantly, new pseudo-elements give you surgical access to parts that were previously unreachable.

The ::picker Pseudo-Element

select::picker(option) targets the popup list itself — every option row inside the opened dropdown. This is where real theming happens: hover states, selected-state highlighting, separators between groups via ::picker(group-start), and even custom checkmarks on chosen items.

select::picker(option) {
  padding: .5rem;
}
select::picker(option):hover {
  background: color-mix(in oklab, var(--accent), white);
}

The selectedcontent Pseudo-Element

selectedcontent lets you style the text currently shown on the closed button — useful for aligning it with your design system's typography or adding a status indicator that changes per selection.

Smooth Open and Close Animations

The popup supports discrete animations, so opening feels native rather than jarring. Pair appearance: base-select with the new transition behavior:

select {
  appearance: base-select;
  transition-behavior: allow-discrete;
}
select::picker(option) {
  opacity: 0;
}
select.open::picker(option) {
  opacity: 1;
}

Combined with @starting-style, you can fade and slide the option list in rather than having it snap open — a small touch that makes a big difference to perceived polish.

The Accessibility Win

This is where base select beats every JavaScript library. Because you are styling the native element instead of replacing it, you keep all the built-in behavior: proper label association, arrow-key navigation, type-ahead search, and screen-reader semantics that work without extra ARIA wiring.

The biggest advantage of appearance: base-select is not visual — it's semantic. You get a fully styled dropdown that still behaves like the native control assistive technology already understands.

With Select2-style libraries, teams routinely had to re-implement focus management and expose hidden inputs for form submission. None of that exists here because there is no replacement element — just better styling on the original one.

Progressive Enhancement in Production

The feature is still rolling out across browsers, so production code needs a graceful strategy. The @supports rule is your friend:

select {
  /* fallback: keep native look */
}
@supports (appearance: base-select) {
  select { appearance: base-select; }
}

This pattern means browsers without support render the plain, accessible native dropdown — perfectly usable — while modern engines get the fully themed version. There is no reason to ship a JavaScript library as a fallback for unsupported browsers; the un-styled native control remains functional and semantic.

A Production Checklist

  • Always pair base-select with an explicit height or padding — base styles are intentionally minimal.
  • Test keyboard interaction: arrow keys, Escape to close, Enter to confirm should all work without extra handlers.
  • Use ::picker(option) for hover and selected states instead of relying on global selectors that leak into the closed button.
  • Keep a styled fallback in @supports so unsupported browsers still look reasonable, not broken.
  • Add transition-behavior: allow-discrete only where you intend to animate; it changes default transition handling for discrete properties.

What This Removes From Your Bundle

The practical payoff is measurable. A typical Select2 or Choices.js integration ships 20–60 KB of JavaScript plus CSS overrides. For teams running many dropdowns across a dashboard, that adds up to real bytes on the critical path — and real maintenance in custom keyboard handlers.

Replacing those libraries with appearance: base-select removes an entire class of dependency from your project. The same is true for headless UI wrappers built purely to restyle selects; once native styling works, that abstraction layer disappears along with its version churn and accessibility caveats.

Limitations to Know Before Adopting

The feature is not a silver bullet yet. Some interactions — multi-select chips, searchable dropdowns over large option sets, or fully custom layouts per row — still benefit from JavaScript because base select styles the native listbox rather than arbitrary markup. If you need inline images inside options or virtualized lists of thousands of items, hold off.

Browser support is also maturing but not universal, so your @supports fallback must be genuinely good — not an afterthought. Teams should treat base select as a progressive enhancement that elevates the experience where it works rather than a hard requirement.

The Bottom Line

appearance: base-select is one of those rare CSS features that removes code instead of adding it. It replaces an entire ecosystem of JavaScript dropdown libraries with a native, styleable control that keeps its accessibility superpowers intact. Adopt it progressively, keep your fallback honest, and watch the select — long the black sheep of form styling — finally behave like everything else on the page.

Comments