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 select
s.
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 select
s
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 option
s will inherit background styling from the select
, but optgroup
s will not, and there's no way to style the background of optgroup
s in Firefox. This could result in Firefox having option
s 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 optgroup
s. 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 select
s (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.