How do I style a <select> dropdown with only CSS?
Purely with standard CSS, you can customize a <select>
’s overall appearance (font, colors, borders, etc.) and hide the default arrow in many browsers by removing the built-in “native” styles (using appearance: none;
). However, fully customizing the dropdown’s options list (such as styling the scroll bar or individual options in a truly custom way) is generally beyond the scope of pure CSS, since most user agents render <select>
options with OS-level widgets.
Below are some common techniques and limitations:
1. Basic Styling (Font, Colors, Border)
select { font: inherit; /* match parent font */ color: #333; /* text color */ background-color: #f2f2f2; border: 1px solid #ccc; padding: 0.5em; border-radius: 4px; }
- What Works: Font family/size, text color, background color, border style, padding, border-radius, etc.
- Limitations: The dropdown “options” interface often follows the OS’s native UI. You can set some colors for the open list in some browsers, but consistency is not guaranteed.
2. Removing the Default Arrow
appearance: none;
Many modern browsers support the appearance: none;
property (with vendor prefixes for older compatibility) to remove the default arrow/indicator:
select { appearance: none; /* standard syntax */ -webkit-appearance: none; /* Safari/Chrome */ -moz-appearance: none; /* Firefox (limited) */ background: #f2f2f2; border: 1px solid #ccc; padding: 0.5em 2em 0.5em 0.5em; /* some extra right padding */ border-radius: 4px; cursor: pointer; } /* Remove the arrow in IE/Edge by hiding the “expand” button */ select::-ms-expand { display: none; }
- Note: Once you remove the arrow, you may want to add a custom arrow or indicator (e.g., background image on the right side) to show users this is a dropdown.
Example with a Custom Arrow:
.custom-select { appearance: none; background: #fff url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iOCIgdmlld0JveD0iMCAwIDE2IDgiIHhtbDpzcGFjZT0icHJlc2VydmUiIHN0cm9rZT0iIzAwMCI+PHBvbHlnb24gcG9pbnRzPSIwLDAgOCw4IDE2LDAiLz48L3N2Zz4=') no-repeat right 0.75em center/8px 4px; padding-right: 2em; /* ...other styles... */ }
- Explanation:
background: #fff url(...) no-repeat right 0.75em center/8px 4px;
sets a small arrow icon on the right side.padding-right: 2em;
ensures space for the arrow.- The arrow base64-encoded SVG is just an example; you can use any image or icon.
3. Styling the Dropdown Options?
- Limited: By default, the options list is rendered by the OS/Browser UI. Basic CSS (like text color, background) may apply in some browsers, but full customization (e.g., custom fonts, complex hover effects) is inconsistent.
option
pseudo-classes: You can sometimes set basic properties on.custom-select option { background-color: ... }
, but deeper styling (borders, custom hover states) is either not fully supported or heavily browser-dependent.
4. Known Limitations of Pure CSS
- Inconsistent Across Browsers/OS
Each browser may interpret<select>
styling differently, especially on mobile (iOS Safari/Android Chrome often override many styles). - No “Open” State Styling
You can’t reliably style the open dropdown list or the scrollbar purely via standard CSS in all browsers. - Accessibility
Removing native indications (like the arrow) can hurt usability if you don’t provide a clear alternative clue that it’s interactive.
5. When You Need Full Customization
- Custom Dropdown with HTML + JS
If you need a truly stylable dropdown (animated open, custom hover styles, custom icons per option, etc.), consider building a custom dropdown using<ul>
/<li>
or a library (e.g., a React/Vue component, or a vanilla JS plugin). - Still keep accessibility in mind (e.g., ARIA roles, keyboard navigation).
Summary
- Yes, you can style a
<select>
with some custom properties: font, color, border, background. - Yes, you can hide the native arrow with
appearance: none;
(plus vendor prefixes and::-ms-expand
). Then add your own icon if desired. - No, you cannot reliably restyle the options list or the open dropdown in a heavily customized way with pure CSS, due to OS-level native rendering and limited spec support.
For advanced or consistent cross-browser styling, a custom-coded dropdown using JavaScript is the typical solution. If you just want a simple styled select with a custom arrow, the techniques above (removing default arrow + background image arrow) can get you a decent result.