appearance: none for Custom Select Boxes: The Complete Guide
AI generated
{ }
@
CSS · Forms · Select · Accessibility
appearance: none for Custom Select Boxes
the native arrow disappears, accessibility stays

The native browser arrow of a select element rarely matches a carefully considered design system, and appearance: none removes exactly that one visual detail, without impairing built in keyboard control, type ahead search, or screen reader announcement. Anyone who uses this technique correctly saves the entire rebuild of a dropdown in JavaScript.

17 min read appearance: none · select · arrow icon · focus ring Chrome · Firefox · Safari · Edge

1. The core problem: the native select arrow rarely fits the design

Every select element carries its own system typical arrow graphic in every browser, signaling the collapsible nature of the element. This arrow is part of the user agent rendering and is drawn differently in Chrome, Firefox and Safari, usually a gray triangular arrow in a gray box, which visually rarely fits a modern design system. Before appearance: none, the only way to remove this arrow was to hide the entire native select and rebuild a custom dropdown from a div structure and JavaScript.

That rebuild involves significant effort, because a native select automatically brings keyboard control, type ahead search, mobile picker UI and ARIA semantics that all have to be manually reimplemented in a hand built dropdown. appearance: none solves this dilemma by only removing the default visual rendering, including the arrow, while the element itself stays a real select, with all native behaviors unchanged.

2. What appearance: none exactly does to a select

The appearance: none property, applied to a select element, removes the entire system typical rendering, that is border, background and the arrow, and visually resets the element to zero, comparable to a styleless div. From this point on, custom CSS takes full control over background color, border, padding and font, exactly like any other element. It matters that -webkit-appearance: none and -moz-appearance: none are set in addition to the standard property appearance: none, because older Safari and Firefox versions only supported the standardized notation with a delay.

A detail that is often overlooked: without appearance: none, many browsers completely ignore certain CSS properties on a select element, say background-image or a custom border-radius combined with a custom background. Only once native rendering has been disabled with appearance: none do these CSS properties reliably take effect in all relevant browsers.


select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  /* Without appearance: none, background-image is often ignored on select */
  background-color: white;
  border: 1px solid #d1d5db;
  border-radius: 0.5rem;
  padding: 0.6rem 2.5rem 0.6rem 1rem;
  font-size: 1rem;
  cursor: pointer;
}

3. Adding a custom arrow icon via background-image

Once the native arrow has been removed, the user lacks a visual signal that this is a collapsible element. The established solution is a custom arrow icon, embedded via background-image with an inline SVG as a data URI, positioned via background-position at the right edge of the element. This technique renders identically across browsers, because background-image needs no special prefixes and is rendered the same way in every browser.

An important detail for multilingual or RTL layouts: instead of hard coding background-position: right, inset-inline-end or a logical positioning approach should be used, so the arrow automatically appears on the left in a right to left language, instead of visually sticking incorrectly to the right edge. The same logic applies to the padding area that creates room for the icon: padding-inline-end instead of padding-right.


select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-color: white;
  border: 1px solid #d1d5db;
  border-radius: 0.5rem;
  padding-block: 0.6rem;
  padding-inline: 1rem 2.5rem;
  font-size: 1rem;
  cursor: pointer;

  /* Custom arrow icon via inline SVG data URI */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='%236d28d9'%3E%3Cpath d='M5.5 7.5l4.5 5 4.5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.8rem center;
  background-size: 1rem;
}

/* Logical property variant for RTL support */
select {
  background-position: inset-inline-end 0.8rem center;
}

4. Styling the focus state and border consistently

Because appearance: none also removes the operating system's native focus ring, it has to be replaced by a custom CSS rule, otherwise the element loses an important signal for keyboard users. The :focus and :focus-visible selectors take on this task, with :focus-visible being the better choice, because it shows the focus ring only during keyboard navigation and not on every mouse click, which looks visually calmer without impairing keyboard accessibility.

A common mistake at this point: developers remove the focus ring entirely with outline: none, without defining an equivalent replacement. That violates WCAG 2.4.7 and makes the form practically unusable for keyboard users, since it remains unclear which element is currently active. A custom focus state with sufficient contrast, say a colored box-shadow ring, is mandatory as soon as the native ring has been removed via appearance: none.


select {
  -webkit-appearance: none;
  appearance: none;
  border: 1px solid #d1d5db;
  border-radius: 0.5rem;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Custom focus ring, only for keyboard navigation */
select:focus-visible {
  outline: none;
  border-color: #7c3aed;
  box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.35);
}

/* Mouse click focus: subtle, no ring, still visible border change */
select:focus:not(:focus-visible) {
  border-color: #a78bfa;
}

5. Limits: what appearance: none does NOT affect

One of the most important insights when working with appearance: none: the collapsible dropdown list itself, that is the individual option elements, remains fully system typical in most browsers and cannot be styled with regular CSS. Chrome and Firefox continue to render the opened option list in the native operating system style, regardless of how heavily the select element itself has been styled. That means a select individually styled through appearance: none looks completely different from the default in its closed state, but still opens with the same old gray system list.

This limitation is the main reason why many design systems, despite appearance: none, additionally rebuild a completely custom dropdown in JavaScript or Alpine.js, as soon as the option list itself needs to be individually styled too, say with custom hover states, icons next to each option, or a search bar. Anyone who only wants to adjust the closed state gets by fully with appearance: none, anyone who also wants to control the opened list needs either the new appearance: base-select or a complete custom widget.

6. Accessibility: preserving native semantics

The decisive advantage of appearance: none over a fully custom rebuilt dropdown is that the native semantics of a real select element are preserved one hundred percent. Screen readers still correctly announce the element as a "combobox" or "select", read out the number of options, and navigate through the list with arrow keys, without a single ARIA attribute needing manual addition. A hand built dropdown, on the other hand, requires role listbox, aria-expanded, aria-activedescendant, and complete manual keyboard control, which in practice is regularly implemented incorrectly.

A second important point: mobile operating systems like iOS and Android still show their native, touch optimized selection UI for a real select element, even when appearance: none has changed the appearance in the closed state. A hand built dropdown has to rebuild this entire mobile user experience itself, which experience shows is among the most commonly underestimated efforts in custom select implementations.


/* Full accessible custom-styled select, native semantics untouched */
select.custom-select {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  background-color: white;
  border: 1px solid #d1d5db;
  border-radius: 0.5rem;
  padding-block: 0.6rem;
  padding-inline: 1rem 2.5rem;
}

/* No ARIA attributes needed: role, state and keyboard handling are native */
select.custom-select:disabled {
  background-color: #f3f4f6;
  color: #9ca3af;
  cursor: not-allowed;
}

7. appearance: base-select as a future standard

Chrome has introduced a new value, appearance: base-select, meant to close exactly the gap left open by appearance: none: full styleability of the opened option list, while preserving the complete native semantics and keyboard control. With this value, option elements can be given custom padding, hover colors and even icons, without building a single JavaScript widget, and without the accessibility loss of a custom rebuild.

appearance: base-select is not yet available in all browsers at the time of this article and should be used behind an @supports block, with appearance: none plus a manual icon as a fallback for browsers without support. For projects that will be updated over the coming years, it is worth watching this development, because it could make many of the JavaScript custom dropdowns still needed today obsolete in the medium term.


/* Progressive enhancement toward full native custom select styling */
@supports (appearance: base-select) {
  select {
    appearance: base-select;
  }
  select option {
    padding: 0.5rem 1rem;
  }
  select option:hover {
    background: #ede9fe;
  }
}

@supports not (appearance: base-select) {
  select {
    -webkit-appearance: none;
    appearance: none;
    /* fallback: closed state styled, option list stays native */
  }
}

8. Multiple selects and the size attribute together

A special case that leads to different behavior with appearance: none is a select with the multiple attribute or a size attribute greater than one. In that case, the browser no longer renders a collapsible list, but a permanently visible listbox, whose individual rows can be styled directly with option selectors, independent of the limitation described above for classic dropdown selects. Padding, background color in the selected state, and row spacing can be adjusted here through option and option:checked, because the list is no longer part of a separate popup layer.

This quirk makes a multiple select a practical alternative when a design system needs several styleable choices without accepting the complexity of a fully custom dropdown. The downside is a different interaction pattern, multiple selection via Ctrl click or Cmd click, which many end users are not familiar with and therefore usually requires additional hint text in the interface.

9. appearance: none vs. a fully custom dropdown

The choice between appearance: none, the newer appearance: base-select, and a fully hand built dropdown depends on how much control is needed over the opened option list. The following overview compares the four common approaches with their respective effort.

Approach Closed state Opened list Effort
Native select, unstyled Browser default System typical No effort
appearance: none + icon Fully styleable Still system typical Low, a few CSS lines
appearance: base-select Fully styleable Fully styleable Low, but limited browser support
Custom dropdown via JS/Alpine Fully styleable Fully styleable High, ARIA and keyboard manual

Mironsoft

Forms, design systems and accessible UI controls

Select boxes that fit the design and stay accessible?

We style select elements with appearance: none, a custom icon and correct focus state, or build fully custom dropdowns where more control is needed, always with accessibility in mind.

Select redesign

Modernize native selects with a custom icon and focus state

Custom dropdown

Build fully styleable comboboxes with correct ARIA

Accessibility check

Verify forms against WCAG keyboard and screen reader requirements

10. Summary

appearance: none is the right choice for the vast majority of projects that only want to style the closed state of a select element. The property removes border, background and arrow, a custom icon via background-image replaces the native arrow, and a manually defined focus state replaces the removed system ring. The opened option list stays system typical in most browsers, which saves effort and guarantees full keyboard and screen reader support.

Anyone who also wants to style the opened list individually either waits for broader support of appearance: base-select or builds a complete custom dropdown in JavaScript, with the corresponding extra effort for ARIA attributes and keyboard control. For most forms in shops and applications, appearance: none with a custom icon is entirely sufficient.

appearance: none for select boxes — the essentials at a glance

Effect

Removes border, background and arrow of the closed select, full CSS control afterward.

Icon replacement

Custom arrow via background-image, mind logical positioning for RTL support.

Limitation

The opened option list stays system typical in most browsers, appearance: base-select solves this eventually.

Accessibility

Native semantics remain intact, a custom focus ring is mandatory once outline was removed.

11. FAQ: appearance: none for select boxes

1What does appearance: none do to select?
Removes border, background and arrow, makes the element visually neutral, but stays functionally a real select.
2Why doesn't the arrow disappear otherwise?
The arrow belongs to native rendering, only appearance: none disables it fully.
3Can I style the option list?
In most browsers no, that requires appearance: base-select or a custom dropdown.
4Do I have to replace the focus ring?
Yes, otherwise the form violates WCAG 2.4.7 and is unclear for keyboard users.
5Does keyboard control remain intact?
Yes, fully, because the element stays a real select.
6What is appearance: base-select?
A new value for fully styleable option lists with preserved semantics, not yet universally available.
7How do I position the icon for RTL?
Use logical properties like inset-inline-end instead of right.
8What differs with multiple selects?
They render a permanent listbox with directly styleable option rows, unlike classic dropdowns.
9When is a custom dropdown worth it?
When the option list needs custom icons or search fields and base-select isn't enough yet.
10Does it work on mobile devices?
Yes, iOS and Android still show their native picker UI when opening.