Advanced select

Tom Select turns a `<select>` into a searchable, keyboard-friendly dropdown, for long option lists, multi-value fields and options with an avatar or a flag.

Overview

Tom Select attaches to a normal <select class="form-select"> and replaces it with a searchable dropdown. The original <select> stays in the DOM and keeps its value, so it still works in a plain HTML form.

<select class="form-select" id="select-overview" data-placeholder="Pick a fruit">
  <option value="apple">Apple</option>
  <option value="banana">Banana</option>
  <option value="cherry">Cherry</option>
  <option value="date">Date</option>
  <option value="elderberry">Elderberry</option>
</select>

Installation

Install Tom Select with npm:

npm install tom-select
yarn add tom-select
pnpm install tom-select
bun install tom-select

Or include it from a CDN. You need both the script and its stylesheet:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/libs/tom-select/dist/css/tom-select.bootstrap5.min.css" />
<script src="https://cdn.jsdelivr.net/npm/@tabler/[email protected]/dist/libs/tom-select/dist/js/tom-select.base.min.js"></script>

Usage

Basic select

Add class="form-select" to a <select>, give it an id, then attach Tom Select to that id.

<select class="form-select" id="select-basic">
  <option value="apple">Apple</option>
  <option value="banana">Banana</option>
  <option value="cherry">Cherry</option>
</select>
new TomSelect('#select-basic', {
  copyClassesToDropdown: false,
});

Placeholder

Native <select> elements don't support the placeholder attribute, so add data-placeholder instead. Tom Select reads it and shows it as the empty-state text.

<select class="form-select" id="select-placeholder" data-placeholder="Pick a fruit">
  <option value="apple">Apple</option>
  <option value="banana">Banana</option>
  <option value="cherry">Cherry</option>
</select>

Multiple values

Add the multiple attribute to let users pick more than one option. Tom Select shows each pick as a removable tag.

<select class="form-select" id="select-multiple" multiple="true" data-placeholder="Pick fruits">
  <option value="apple">Apple</option>
  <option value="banana">Banana</option>
  <option value="cherry">Cherry</option>
  <option value="date">Date</option>
  <option value="elderberry">Elderberry</option>
</select>
new TomSelect('#select-multiple', {
  copyClassesToDropdown: false,
});

Optgroups

Group related options with <optgroup>. Tom Select shows the group label in the dropdown and keeps it searchable.

<select class="form-select" id="select-optgroup" data-placeholder="Pick a fruit">
  <optgroup label="Citrus">
    <option value="orange">Orange</option>
    <option value="lemon">Lemon</option>
    <option value="lime">Lime</option>
  </optgroup>
  <optgroup label="Berries">
    <option value="strawberry">Strawberry</option>
    <option value="blueberry">Blueberry</option>
    <option value="raspberry">Raspberry</option>
  </optgroup>
</select>

Validation states

Add .is-valid or .is-invalid to the <select> to show a validation state. Tom Select carries the class over to its own wrapper, so the field still shows the usual green or red styling.

<div class="mb-3">
  <label class="form-label">Valid select</label>
  <select class="form-select is-valid" id="select-valid" data-placeholder="Pick a fruit">
    <option value="apple" selected>Apple</option>
    <option value="banana">Banana</option>
  </select>
</div>
<div>
  <label class="form-label">Invalid select</label>
  <select class="form-select is-invalid" id="select-invalid" data-placeholder="Pick a fruit">
    <option value="apple">Apple</option>
    <option value="banana">Banana</option>
  </select>
</div>

Rich options

An option can carry extra markup - an avatar, a flag, a badge - through a data-custom-properties attribute. Read it in a custom render.option / render.item function and show it next to the option text.

<select class="form-select" id="select-avatar" data-placeholder="Assign to…">
  <option value="1" data-custom-properties="<span class=&quot;avatar avatar-xs&quot;>JD</span>">Jane Doe</option>
  <option value="2" data-custom-properties="<span class=&quot;avatar avatar-xs&quot;>MS</span>">Mark Smith</option>
  <option value="3" data-custom-properties="<span class=&quot;avatar avatar-xs&quot;>AK</span>">Amy Kim</option>
</select>
<select class="form-select" id="select-flag" data-placeholder="Pick a country">
  <option value="us" data-custom-properties="<span class=&quot;flag flag-xs flag-country-us&quot;></span>">United States</option>
  <option value="gb" data-custom-properties="<span class=&quot;flag flag-xs flag-country-gb&quot;></span>">United Kingdom</option>
  <option value="de" data-custom-properties="<span class=&quot;flag flag-xs flag-country-de&quot;></span>">Germany</option>
  <option value="fr" data-custom-properties="<span class=&quot;flag flag-xs flag-country-fr&quot;></span>">France</option>
</select>
function renderOption(data, escape) {
  if (data.customProperties) {
    return `<div class="dropdown-item"><span class="dropdown-item-indicator">${data.customProperties}</span>${escape(data.text)}</div>`;
  }
  return `<div>${escape(data.text)}</div>`;
}

new TomSelect('#select-avatar', {
  copyClassesToDropdown: false,
  dropdownParent: 'body',
  render: {
    item: renderOption,
    option: renderOption,
  },
});

Tom Select turns a data-custom-properties attribute into data.customProperties on the option object, so render.option and render.item can read it. escape() keeps user-supplied text safe when it is inserted as HTML.

Common options

These are the options you will need most often. Tom Select has more, and they are listed in its documentation.

Option What it does
copyClassesToDropdown Copies the <select> classes onto the dropdown. Tabler keeps this false and styles the dropdown itself.
dropdownParent Where the dropdown is appended in the DOM, for example 'body' so it is not clipped by a card or modal.
maxItems Maximum number of selected items on a multi-value select.
create true lets users type a value that is not in the option list.
plugins List of Tom Select plugins to enable, for example remove_button.
render.option / render.item Custom render functions for a dropdown option and a selected item.

Accessibility

  • Always add a <label> linked to the <select> with for and id. Tom Select's generated markup does not replace the need for a label.
  • The dropdown can be operated with the keyboard: type to search, arrow keys to move between options, Enter to pick one, and Backspace to remove the last tag on a multi-value select.
  • When using render.option, keep enough text content in the rendered HTML - an avatar or flag alone does not tell a screen reader user which option it is.
  • Escape user-supplied text in custom render functions with the escape argument, so option text can never break out of the generated HTML.

On this page

130 sleek illustrations for your startup's visual identity.