Accessible Styled Form Controls

Styled Single Selects

Published:

Last updated:

Cross-browser styling for the default select element.

Pattern Demo




Pattern Details

Pattern Markup
<label for="ex_custom_select">
  Label Text
</label>
<div class="select">
  <select id="ex_custom_select">
    <option>Option 1</option>
    <option>Option 2</option>
    <option>Option 3</option>
  </select>
</div>

Consistently cross-browser styling of a select and its child elements has never been a straight forward task. The markup pattern outlined here can provide consistent custom styling for a select's default, and focused states. However, with some exceptions, browsers don't allow for much, if any, control over the styling of option and optgroup elements.

The default select

The select has much of its native HTML styling removed by use of vendor prefixed appearance: none. Once those native styles have been removed, the element can be redesigned with additional CSS. Additional browser specific selectors for removing native styling from Microsoft browsers (::-ms-value and ::-ms-expand), and the focus ring from Firefox (:-moz-focusring) are also needed.

The wrapping div.select is in place to provide a position: relative container, and to create and position the :before and :after pseudo elements. These pseudo elements are used to recreate a custom down arrow for the select, and its focus state background color.

Right to left support

Native select elements support right-to-left languages, and so should custom styled selects.

The CSS for this custom style has support for the dir="rtl" attribute, as well as lang="ar" and lang="iw". You may wish to support additional right-to-left languages as well.

Required selects

A select element can have a required attribute, and will trigger an invalid style if the currently selected option has a value set to the empty string. e.g. <option value="">...</option>.

Background colors

The wrapping div also handles the background color to the select. The background styling should be done to this wrapping element, and not the select element itself, to mitigate issues with how option and optgroup elements inconsistently inherit background color styling of the select across browsers. For instance, in Firefox options will inherit background styling from the select, but optgroups will not, and there's no way to style the background of optgroups in Firefox. This could result in Firefox having options that match the background color of their parent select, while any optgroup being stuck with the default grey background.

Internet Explorer and Edge have the best support for styling option and optgroups. But Chrome, Safari and other Webkit based browsers do not provide any support for styling these elements.

In conclusion, to "style" a standard select element and give it consistent design across all browsers, its advised to keep the option and optgroup styling as close to browser defaults as possible. If a fully styleable single-select form control is desired, an ARIA listbox might be the way to go. Note, there's quite a bit to do to recreate native select functionality, and keeping small/touch screens in mind.

Affects on Screen Reader Announcements?

There are no alterations to how a screen reader should announce styled select elements when following this pattern.

Note there is a bug with selects (styled or not) with VoiceOver on iOS. When hitting the "done" button, in the native picker that displays on screen, VoiceOver may not return focus to the select element that had been previously activated. This is unfortunately a long standing bug with VoiceOver, but here's a issue from 2017 that appears to be related.

Continue reading

For more information and guidance on styling select elements, check out Styling a Select Like It’s 2019 by Scott Jehl.