SkillAgentSearch skills...

Choices

A vanilla JS customisable select box/text input plugin ⚡️

Install / Use

/learn @Choices-js/Choices

README

Choices.js Actions Status Actions Status npm

A vanilla, lightweight (~20kb gzipped 🎉), configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency.

Demo

TL;DR

  • Lightweight
  • No jQuery dependency
  • Configurable sorting
  • Flexible styling
  • Fast search/filtering
  • Clean API
  • Right-to-left support
  • Custom templates

Interested in writing your own ES6 JavaScript plugins? Check out ES6.io for great tutorials! 💪🏼

Sponsored by:

<p align="center"> <a href="https://forums.sufficientvelocity.com/" target="_blank" rel="noopener noreferrer"> <img src="https://forums.sufficientvelocity.com/data/assets/static_light_logo.svg" alt="Sufficient Velocity" width="310" height="108"> </a> </p> <p align="center"> <a href="https://wanderermaps.com/" target="_blank" rel="noopener noreferrer"> <img src="https://cdn.shopify.com/s/files/1/0614/3357/7715/files/Logo_BlackWithBackground_200x.png?v=1644802773" alt="Wanderer Maps logo"> </a> </p>

Table of Contents

Installation

With NPM:

npm install choices.js

With Yarn:

yarn add choices.js

From a CDN:

Notes:

  • There is sometimes a delay before the latest version of Choices is reflected on the CDN.
  • Examples below pin a version (v11.1.0). Check latest release and update v11.1.0 to the latest tag before using.
<!-- Include base CSS (optional) -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/base.min.css"
/>
<!-- Or versioned -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/choices.js@11.1.0/public/assets/styles/base.min.css"
/>

<!-- Include Choices CSS -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css"
/>
<!-- Or versioned -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/choices.js@11.1.0/public/assets/styles/choices.min.css"
/>

<!-- Include Choices JavaScript (latest) -->
<script src="https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js"></script>
<!-- Or versioned -->
<script src="https://cdn.jsdelivr.net/npm/choices.js@11.1.0/public/assets/scripts/choices.min.js"></script>

Or include Choices directly:

<!-- Include base CSS (optional) -->
<link rel="stylesheet" href="public/assets/styles/base.min.css" />
<!-- Include Choices CSS -->
<link rel="stylesheet" href="public/assets/styles/choices.min.css" />
<!-- Include Choices JavaScript -->
<script src="/public/assets/scripts/choices.min.js"></script>

CSS/SCSS

The use of import of css/scss is supported from webpack.

In .scss:

@import "choices.js/src/styles/choices";

In .js/.ts:

import "choices.js/public/assets/styles/choices.css";

Setup

Note: If you pass a selector which targets multiple elements, the first matching element will be used. Versions prior to 8.x.x would return multiple Choices instances.

  // Pass single element
  const element = document.querySelector('.js-choice');
  const choices = new Choices(element);

  // Pass reference
  const choices = new Choices('[data-trigger]');
  const choices = new Choices('.js-choice');

  // Pass jQuery element
  const choices = new Choices($('.js-choice')[0]);

  // Passing options (with default options)
  const choices = new Choices(element, {
    silent: false,
    items: [],
    choices: [],
    renderChoiceLimit: -1,
    maxItemCount: -1,
    closeDropdownOnSelect: 'auto',
    singleModeForMultiSelect: false,
    addChoices: false,
    addItems: true,
    addItemFilter: (value) => !!value && value !== '',
    removeItems: true,
    removeItemButton: false,
    removeItemButtonAlignLeft: false,
    editItems: false,
    allowHTML: false,
    allowHtmlUserInput: false,
    duplicateItemsAllowed: true,
    delimiter: ',',
    paste: true,
    searchEnabled: true,
    searchChoices: true,
    searchDisabledChoices: false,
    searchFloor: 1,
    searchResultLimit: 4,
    searchFields: ['label', 'value'],
    position: 'auto',
    resetScrollPosition: true,
    shouldSort: true,
    shouldSortItems: false,
    sorter: (a, b) => sortByAlpha,
    shadowRoot: null,
    placeholder: true,
    placeholderValue: null,
    searchPlaceholderValue: null,
    prependValue: null,
    appendValue: null,
    renderSelectedChoices: 'auto',
    searchRenderSelectedChoices: true,
    loadingText: 'Loading...',
    noResultsText: 'No results found',
    noChoicesText: 'No choices to choose from',
    itemSelectText: 'Press to select',
    uniqueItemText: 'Only unique values can be added',
    customAddItemText: 'Only values matching specific conditions can be added',
    addItemText: (value, rawValue) => {
      return `Press Enter to add <b>"${value}"</b>`;
    },
    removeItemIconText: () => `Remove item`,
    removeItemLabelText: (value, rawValue) => `Remove item: ${value}`,
    maxItemText: (maxItemCount) => {
      return `Only ${maxItemCount} values can be added`;
    },
    valueComparer: (value1, value2) => {
      return value1 === value2;
    },
    classNames: {
      containerOuter: ['choices'],
      containerInner: ['choices__inner'],
      input: ['choices__input'],
      inputCloned: ['choices__input--cloned'],
      list: ['choices__list'],
      listItems: ['choices__list--multiple'],
      listSingle: ['choices__list--single'],
      listDropdown: ['choices__list--dropdown'],
      item: ['choices__item'],
      itemSelectable: ['choices__item--selectable'],
      itemDisabled: ['choices__item--disabled'],
      itemChoice: ['choices__item--choice'],
      description: ['choices__description'],
      placeholder: ['choices__placeholder'],
      group: ['choices__group'],
      groupHeading: ['choices__heading'],
      button: ['choices__button'],
      activeState: ['is-active'],
      focusState: ['is-focused'],
      openState: ['is-open'],
      disabledState: ['is-disabled'],
      highlightedState: ['is-highlighted'],
      selectedState: ['is-selected'],
      flippedState: ['is-flipped'],
      loadingState: ['is-loading'],
      invalidState: ['is-invalid'],
      notice: ['choices__notice'],
      addChoice: ['choices__item--selectable', 'add-choice'],
      noResults: ['has-no-results'],
      noChoices: ['has-no-choices'],
    },
    // Choices uses the great Fuse library for searching. You
    // can find more options here: https://fusejs.io/api/options.html
    fuseOptions: {
      includeScore: true
    },
    labelId: '',
    callbackOnInit: null,
    callbackOnCreateTemplates: null,
    appendGroupInSearch: false,
  });

Terminology

| Word | Definition | | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Choice | A choice is a value a user can select. A choice would be equivalent to the <option></option> element within a select input. | | Group | A group is a collection of choices. A group should be seen as equivalent to a <optgroup></optgroup> element within a select input. | | Item | An item is an inputted value (text input) or a selected choice (select element). In the context of a select element, an item is equivalent to a selected option element: <option value="Hello" selected></option> whereas in the context of a text input an item is equivalent to <input type="text" value="Hello"> |

Input Types

Choices works with the following input types, referenced in the documentation as noted.

| HTML Element | Documentation "Input Type" | | -------------------------------------------------------------------------------------------------------| -------------------------- | | <input type="text"> | text | | <select> | select-one | | <select multiple>

View on GitHub
GitHub Stars6.8k
CategoryDevelopment
Updated7h ago
Forks639

Languages

JavaScript

Security Score

100/100

Audited on Apr 1, 2026

No findings