About this snippet

A status field that looks like a designed dropdown, with a colored dot beside every option and a check beside the chosen one, yet it is a plain select element. Keyboard behavior, screen reader support and form submission stay native because nothing has been replaced.

The switch is appearance set to base-select on the select and on its ::picker(select) pseudo-element. That opts the control into the browser's stylable mode, where the button, the picker and each option are ordinary boxes that take normal CSS, and options may contain elements such as the swatch spans here. The selectedcontent element mirrors the chosen option into the button, and ::checkmark is the tick the browser draws beside the current choice.

Customizable select shipped in Chrome and Edge in 2025. A browser without it ignores the appearance value and renders its own select, so the field never breaks.

Size
3.1 KB
Uses
HTML, CSS
Loads
Nothing external
Views
37
<form class="panel">
  <h1>Ticket details</h1>
  <label for="status">Status</label>
  <select id="status" name="status" class="status">
    <button>
      <selectedcontent></selectedcontent>
    </button>
    <option value="open"><span class="dot open"></span>Open</option>
    <option value="progress" selected><span class="dot progress"></span>In progress</option>
    <option value="review"><span class="dot review"></span>In review</option>
    <option value="done"><span class="dot done"></span>Done</option>
    <option value="blocked"><span class="dot blocked"></span>Blocked</option>
  </select>
  <p class="note">Open the list. Options carry real markup and the check mark is drawn by the browser.</p>
</form>
*, *::before, *::after {
  box-sizing: border-box;
}

body {
  font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  margin: 0;
  background: #f1f5f9;
  color: #0f172a;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  min-height: 100vh;
  padding: 60px 20px;
}

.panel {
  width: 100%;
  max-width: 360px;
  background: #ffffff;
  padding: 32px;
  border-radius: 20px;
  box-shadow: 0 20px 40px -20px rgba(15, 23, 42, 0.25);
}

.panel h1 {
  font-size: 1.375rem;
  margin: 0 0 20px;
}

.panel label {
  display: block;
  font-size: 0.875rem;
  font-weight: 600;
  margin-bottom: 6px;
}

.status,
.status::picker(select) {
  appearance: base-select;
}

.status {
  width: 100%;
  font: inherit;
  padding: 11px 14px;
  border: 1.5px solid #cbd5e1;
  border-radius: 10px;
  background: #ffffff;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.status:focus-visible,
.status:open {
  outline: 0;
  border-color: #2563eb;
  box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.15);
}

.status::picker-icon {
  color: #64748b;
  transition: rotate 0.2s ease;
}

.status:open::picker-icon {
  rotate: 180deg;
}

.status::picker(select) {
  margin-top: 6px;
  padding: 6px;
  border: 0;
  border-radius: 12px;
  background: #ffffff;
  box-shadow: 0 20px 40px -12px rgba(15, 23, 42, 0.3);
  opacity: 0;
  translate: 0 -6px;
  transition: opacity 0.16s ease, translate 0.16s ease, overlay 0.16s allow-discrete, display 0.16s allow-discrete;
}

.status:open::picker(select) {
  opacity: 1;
  translate: 0 0;
}

@starting-style {
  .status:open::picker(select) {
    opacity: 0;
    translate: 0 -6px;
  }
}

.status option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 8px;
  font: inherit;
  cursor: pointer;
}

.status option:hover,
.status option:focus-visible {
  background: #f1f5f9;
  outline: 0;
}

.status option:checked {
  font-weight: 600;
}

.status option::checkmark {
  order: 1;
  margin-left: auto;
  color: #2563eb;
}

selectedcontent {
  display: flex;
  align-items: center;
  gap: 10px;
}

.dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex: 0 0 auto;
}

.dot.open { background: #2563eb; }
.dot.progress { background: #f59e0b; }
.dot.review { background: #8b5cf6; }
.dot.done { background: #16a34a; }
.dot.blocked { background: #dc2626; }

.note {
  margin: 16px 0 0;
  font-size: 0.8125rem;
  color: #64748b;
  line-height: 1.5;
}
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save