CSS
Web Design
Web Development
HTML Select
Front-End Development

How do I style a <select> dropdown with only CSS?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

You can style a native select control quite well with CSS, but only within the limits of what browsers expose. The closed field can be customized reliably, while the opened dropdown list is still mostly controlled by the browser and operating system.

Styling the Closed Control

The safest approach is to keep the real select element and style the visible field around it. That preserves keyboard behavior, screen-reader support, and mobile-friendly platform interactions.

html
1<label class="field">
2  <span class="field-label">Country</span>
3  <div class="select-wrap">
4    <select>
5      <option>Canada</option>
6      <option>United States</option>
7      <option>Japan</option>
8    </select>
9  </div>
10</label>
css
1.field {
2  display: grid;
3  gap: 0.5rem;
4  max-width: 20rem;
5  font: 500 0.95rem/1.4 system-ui, sans-serif;
6  color: #1f2937;
7}
8
9.select-wrap {
10  position: relative;
11}
12
13.select-wrap select {
14  appearance: none;
15  -webkit-appearance: none;
16  width: 100%;
17  padding: 0.85rem 2.75rem 0.85rem 1rem;
18  border: 1px solid #cbd5e1;
19  border-radius: 0.75rem;
20  background: #ffffff;
21  color: #111827;
22  font: inherit;
23}
24
25.select-wrap select:focus {
26  outline: none;
27  border-color: #2563eb;
28  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.15);
29}

This handles the field itself: spacing, typography, border, and focus treatment.

Replacing the Native Arrow

Once you remove the browser's default appearance, you usually need to draw your own arrow. The standard pure-CSS pattern is to place it on a wrapper with a pseudo-element.

css
1.select-wrap::after {
2  content: "";
3  position: absolute;
4  right: 1rem;
5  top: 50%;
6  width: 0.6rem;
7  height: 0.6rem;
8  border-right: 2px solid #475569;
9  border-bottom: 2px solid #475569;
10  transform: translateY(-70%) rotate(45deg);
11  pointer-events: none;
12}

Using the wrapper matters because pseudo-elements on the select itself are not consistently reliable across browsers. The wrapper solution keeps the markup simple and the control accessible.

What You Can and Cannot Control

CSS works well for the closed state of the control. You can usually control:

  • padding and width,
  • border and corner radius,
  • colors and fonts,
  • focus and disabled states,
  • the custom arrow treatment.

The opened popup is a different story. Browser engines and operating systems render the options list using native UI components, so things like row height, full hover styling, scrollbars, and popup animation are not consistently customizable.

That means "style a dropdown with only CSS" is realistic if you mean the collapsed control. It is not realistic if you mean turning the opened menu into a fully custom visual component across every browser.

Styling States Cleanly

State styling is often more valuable than over-customizing the arrow. Focus, error, and disabled states make the control feel deliberate and easier to use.

css
1.select-wrap select:disabled {
2  background: #f1f5f9;
3  color: #94a3b8;
4  cursor: not-allowed;
5}
6
7.select-wrap.error select {
8  border-color: #dc2626;
9  box-shadow: 0 0 0 4px rgba(220, 38, 38, 0.12);
10}

These visual states matter more for usability than trying to force exact pixel-level control over the native popup.

When CSS-Only Stops Being Enough

If the requirement is searchable options, grouped icons, custom keyboard behavior, animated panels, or rich option content, you are no longer working with a plain native control. At that point you need a custom widget built with HTML, CSS, and JavaScript, plus careful accessibility work.

That is a bigger project. A native select remains the right choice when you want reliability, low complexity, and standard browser behavior.

Common Pitfalls

  • Expecting the open dropdown popup to be as fully styleable as an ordinary div.
  • Removing native appearance and forgetting to add a visible focus style.
  • Hiding the real select and replacing it with a fake non-accessible control.
  • Drawing the custom arrow on the select itself instead of using a wrapper.
  • Testing in only one browser and assuming all other engines will match exactly.

Summary

  • CSS can style the closed select control well, but not the open popup uniformly.
  • 'appearance: none plus a wrapper and pseudo-element is the usual pure-CSS technique.'
  • Keep the real native control to preserve accessibility and keyboard support.
  • Focus, disabled, and error states are worth more attention than extreme visual customization.
  • If you need a fully custom dropdown experience, CSS alone is not enough.

Course illustration
Course illustration

All Rights Reserved.