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-selectyarn add tom-selectpnpm install tom-selectbun install tom-selectOr 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="avatar avatar-xs">JD</span>">Jane Doe</option>
<option value="2" data-custom-properties="<span class="avatar avatar-xs">MS</span>">Mark Smith</option>
<option value="3" data-custom-properties="<span class="avatar avatar-xs">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="flag flag-xs flag-country-us"></span>">United States</option>
<option value="gb" data-custom-properties="<span class="flag flag-xs flag-country-gb"></span>">United Kingdom</option>
<option value="de" data-custom-properties="<span class="flag flag-xs flag-country-de"></span>">Germany</option>
<option value="fr" data-custom-properties="<span class="flag flag-xs flag-country-fr"></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>withforandid. 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
escapeargument, so option text can never break out of the generated HTML.
