<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
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-expand), and the focus ring from Firefox (
:-moz-focusring) are also needed.
div.select is in place to provide a
position: relative container, and to create and position the
: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
select elements support right-to-left languages, and so should custom styled
The CSS for this custom style has support for the
dir="rtl" attribute, as well as
lang="iw". You may wish to support additional right-to-left languages as well.
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.
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
optgroup elements inconsistently inherit background color styling of the
select across browsers. For instance, in Firefox
options will inherit background styling from the
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
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
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.