Skip to content

Select — HTML & CSS

A custom listbox with an optional type-to-filter search box. Keyboard accessible, closes on outside click, writes the chosen value into a hidden input for form submission.

Wiring it up in JS (init, events, API, Vue) is on the JavaScript page.

Live example

Theme:

Color

default
danger
info
primary
success
warning

Search — add a .UIselect-options__search <li> to type-to-filter

Custom icon — swap the SVG inside .UIselect-arrow (here a magnifier + search)

Search a fruit

Size — xsm · sm · default · lg

xsm
sm
default
lg

Shape (no color) — r-0 · default · r-round

r-0
default
r-round

Width — expand (fills the parent)

expand

Caption — shared .UIlabel above the control

Fruit Pick your favorite fruit.Pick a fruit

Last ui-select-change:

Markup

A .UIselect container holds the displayed .UIselect-selected label, an arrow, a hidden <input> (receives the value), and a .UIselect-options list. Add a .UIselect-options__search <li> to enable filtering; mark the default with aria-selected="true":

html
<div class="UIselect primary" id="fruit" tabindex="0" role="listbox">
  <span class="UIselect-selected">Pick a fruit</span>
  <span class="UIselect-arrow"><!-- chevron svg --></span>
  <input type="hidden" name="fruit" />

  <ul class="UIselect-options" hidden>
    <li class="UIselect-options__search" role="search">
      <input type="text" aria-label="Search options" />
    </li>
    <li class="UIselect-options__items" role="presentation">
      <ul role="group">
        <li role="option" data-value="apple">Apple</li>
        <li role="option" data-value="banana">Banana</li>
        <li role="presentation" class="divider" aria-hidden="true"></li>
        <li role="option" data-value="mango" aria-selected="true">Mango</li>
      </ul>
    </li>
  </ul>
</div>

A <li class="divider"> draws a separator; omit the search <li> for a plain dropdown.

Caption label

Select has no built-in caption. Add the shared .UIlabel class as the first child to put a title above the control — it floats out of flow, so the layout is untouched and the box reserves the room above it:

html
<div class="UIselect primary" id="fruit" tabindex="0" role="listbox" aria-labelledby="fruit-cap">
  <span class="UIlabel" id="fruit-cap">Fruit</span>
  <span class="UIselect-selected">Pick a fruit</span>
  <input type="hidden" name="fruit" />
  <ul class="UIselect-options" hidden>
    <li class="UIselect-options__items" role="presentation">
      <ul role="group">
        <li role="option" data-value="apple">Apple</li>
        <li role="option" data-value="banana">Banana</li>
      </ul>
    </li>
  </ul>
</div>

A nested .UIql help icon inherits the select's theme. Point the control at the caption with aria-labelledby for screen readers.

Minimal markup

The smallest working Select — no search box, no arrow, no color:

html
<div class="UIselect" tabindex="0" role="listbox">
  <span class="UIselect-selected">Select an option</span>
  <input type="hidden" name="example" />
  <ul class="UIselect-options" hidden>
    <li class="UIselect-options__items" role="presentation">
      <ul role="group">
        <li role="option" data-value="1">Option 1</li>
        <li role="option" data-value="2">Option 2</li>
      </ul>
    </li>
  </ul>
</div>