Release candidate (RC)

This component is in the Release Candidate phase and its API is considered stable. Minor adjustments may still occur before the final release.

Bootstrap 5 Chip Input

Chip input

Bootstrap Chip Input component for CoreUI — create tag-like multi-value inputs for skills, categories, or recipients with keyboard support, selection, and form integration.

🤖 Looking for the LLM-optimized version? View llm.md

Overview

The CoreUI Bootstrap Chip Input component lets users enter multiple values as chips inside a single field. Use it as a tag input, multi-value selector, or token field for skills, categories, email recipients, and more. The chip input component supports keyboard-friendly entry, chip removal, and optional selection for bulk actions.

  • Type values and press Enter (or a separator) to create chips.
  • Chips can be removable and selectable.
  • The input stays inline and grows as you type.
  • Full form integration via a hidden input with configurable name.

When to use Chip Input

Use the Bootstrap Chip Input component when you need:

  • A tag input or token field for free-form multi-value entry
  • An email or recipient input where users add multiple addresses
  • A skills or category selector in forms
  • A filterable multi-select that integrates with standard HTML forms

Basic example

Wrap chips and add data-coreui-chip-input to enable behavior.

JavaScript TypeScript Accessibility
html
<div class="chip-input" data-coreui-chip-input data-coreui-name="chipInputBasicExample" data-coreui-placeholder="Add a skill...">
  <label class="chip-input-label" for="skillsInputBasic">Skills:</label>
  <span class="chip">JavaScript</span>
  <span class="chip">TypeScript</span>
  <span class="chip">Accessibility</span>
</div>
Note: The <input class="chip-input-field"> is created automatically by the component when initialized. You can also add it manually in the markup if preferred. Additionally, a hidden input is generated automatically to submit chip values with the form. The name attribute of this hidden input is taken from the data-coreui-name attribute (e.g., data-coreui-name="chipInputBasicExample").
<div class="chip-input" data-coreui-chip-input data-coreui-placeholder="Add a skill...">
  <label class="chip-input-label" for="skillsInputBasic">Skills:</label>
  <span class="chip">JavaScript</span>
  <span class="chip">TypeScript</span>
  <span class="chip">Accessibility</span>
  <input type="text" class="chip-input-field" name="skillsInputBasic" placeholder="Add a skill...">
</div>

Variants

Use contextual chip classes inside Bootstrap 5 Chip Input to represent categories, status, or priority.

Feature Approved Needs review Blocking
html
<div class="chip-input" data-coreui-chip-input data-coreui-name="issues" data-coreui-placeholder="Add label...">
  <span class="chip chip-primary">Feature</span>
  <span class="chip chip-success">Approved</span>
  <span class="chip chip-warning">Needs review</span>
  <span class="chip chip-danger">Blocking</span>
</div>

In the example below, the chip color is assigned dynamically based on the chip text using the chipClassName callback. Each value (e.g., Feature or Blocking) maps to a contextual class, so chips remain visually consistent even when added programmatically.

html
<div id="chipVariants" class="chip-input"></div>

The JavaScript below initializes the example:

const chipInputElement = document.querySelector('#chipVariants')
const chipInput = new coreui.ChipInput(chipInputElement, {
  // Class is resolved dynamically from chip value.
  chipClassName(value) {
    const variants = {
      approved: 'chip-success',
      blocking: 'chip-danger',
      feature: 'chip-primary',
      'needs review': 'chip-warning'
    }

    return variants[value.trim().toLowerCase()] || 'chip-secondary'
  },
  placeholder: 'Add a bug...'
})

chipInput.add('Feature')

Sizes

Use chip-input-sm and chip-input-lg to match surrounding form controls. Default size is provided by .chip-input without a size modifier.

HTML
JavaScript
TypeScript
html
<div class="chip-input chip-input-sm mb-3" data-coreui-chip-input data-coreui-placeholder="Add small tag...">
  <label class="chip-input-label" for="skillsInputSm">Small</label>
  <span class="chip">HTML</span>
</div>

<div class="chip-input mb-3" data-coreui-chip-input data-coreui-placeholder="Add default tag...">
  <label class="chip-input-label" for="skillsInputMd">Default</label>
  <span class="chip">JavaScript</span>
</div>

<div class="chip-input chip-input-lg" data-coreui-chip-input data-coreui-placeholder="Add large tag...">
  <label class="chip-input-label" for="skillsInputLg">Large</label>
  <span class="chip">TypeScript</span>
</div>

Empty state

Start with just the input and let users add chips as they type.

html
<div class="chip-input" data-coreui-chip-input data-coreui-name="tags" data-coreui-placeholder="Start typing tags..."></div>

With label

Use a standard form label for accessibility.

Vue Vite
Press Enter or comma to add a value.
html
<div class="mb-3">
  <label class="form-label" for="techStackInput">Tech stack</label>
  <div class="chip-input" data-coreui-chip-input data-coreui-name="techStack" data-coreui-placeholder="Add package...">
    <span class="chip">Vue</span>
    <span class="chip">Vite</span>
  </div>
  <div class="form-text">Press Enter or comma to add a value.</div>
</div>

Disabled

Set disabled state on the component to make the input and managed chips non-interactive. You can use either the disabled class or the data-coreui-disabled="true" option. For disabled, non-removable chips, combine it with data-coreui-removable="false".

Read only Locked
html
<div class="chip-input" data-coreui-chip-input data-coreui-disabled="true" data-coreui-removable="false" data-coreui-placeholder="Input disabled">
  <span class="chip">Read only</span>
  <span class="chip">Locked</span>
</div>

Readonly

Use readonly state when chips should stay visible and focusable, but values must not change. Set data-coreui-readonly="true" (or readonly: true in JavaScript) to block adding and removing chips.

JavaScript TypeScript
html
<div class="chip-input" data-coreui-chip-input data-coreui-readonly="true" data-coreui-placeholder="Read-only values">
  <span class="chip">JavaScript</span>
  <span class="chip">TypeScript</span>
</div>

Selectable chips

Enable selection for chips managed by Chip Input. In this example, select.coreui.chip-input updates a live list of selected values below the field.

Design Backend QA DevOps

Selected chips: None

html
<div id="chipSelectable" class="chip-input">
  <span class="chip">Design</span>
  <span class="chip">Backend</span>
  <span class="chip active">QA</span>
  <span class="chip active">DevOps</span>
</div>
<p class="form-text mt-2 mb-0">Selected chips: <span id="chipSelectableOutput">None</span></p>
const chipSelectableElement = document.querySelector('#chipSelectable')
const chipSelectableOutput = document.querySelector('#chipSelectableOutput')

const chipSelectable = new coreui.ChipInput(chipSelectableElement, {
  placeholder: 'Add team role...',
  selectable: true
})

const updateSelectedOutput = selected => {
  chipSelectableOutput.textContent = selected.length > 0 ? selected.join(', ') : 'None'
}

chipSelectableElement.addEventListener('select.coreui.chip-input', event => {
  updateSelectedOutput(event.selected)
})

chipSelectable.add('Frontend')
chipSelectable.add('Security')
updateSelectedOutput(chipSelectable.getSelectedValues())

Usage

Initialize the Bootstrap Chip Input component via data attributes or JavaScript. The chip input component automatically creates a hidden form input to submit all chip values with the form.

Via data attributes

Add data-coreui-chip-input to initialize the chip input component. Options can be passed as data-coreui-* attributes.

<div class="chip-input" data-coreui-chip-input data-coreui-name="skills" data-coreui-placeholder="Add tags..." data-coreui-separator=","></div>

When initialized, Chip Input creates a hidden input to submit values with the form.
Use name (or data-coreui-name) to control the submitted field name.

Via JavaScript

const chipInputElement = document.querySelector('.chip-input')
const chipInput = coreui.ChipInput.getOrCreateInstance(chipInputElement, {
  separator: ',',
  maxChips: 5
})

Options

Options can be passed using data attributes or JavaScript. To do this, append an option name to data-coreui-, such as data-coreui-animation="{value}". Remember to convert the case of the option name from “camelCase” to “kebab-case” when using data attributes. For instance, you should write data-coreui-custom-class="beautifier" rather than data-coreui-customClass="beautifier".

Starting with CoreUI 4.2.0, all components support an experimental reserved data attribute named data-coreui-config, which can contain simple component configurations as a JSON string. If an element has attributes data-coreui-config='{"delay":50, "title":689}' and data-coreui-title="Custom Title", then the final value for title will be Custom Title, as the standard data attributes will take precedence over values specified in data-coreui-config. Moreover, existing data attributes can also hold JSON values like data-coreui-delay='{"show":50, "hide":250}'.

Option Type Default Description
chipClassName string | function | null null Adds classes to chips. Use a string for all chips or a function (value) => className for per-chip styling.
disabled boolean false Disables the input and marks managed chips as non-interactive.
readonly boolean false Prevents adding and removing chips while keeping input focus behavior.
id string | null auto-generated Custom id for the generated hidden input.
name string | null auto-generated Name for the generated hidden input used in form submission.
separator string | null ',' Character that triggers chip creation when typed. Set to null to disable.
maxChips number | null null Maximum number of chips allowed. null for unlimited.
placeholder string '' Placeholder text for dynamically created inputs.
selectable boolean false Enables selection behavior for chips managed by Chip Input.
removable boolean true Add remove buttons to created chips.
removeIcon string SVG HTML string for the remove button icon.
createOnBlur boolean true Create a chip from the input value when the input loses focus.

Methods

Method Description
add(value) Adds a chip with the given value. Returns the chip element or null if rejected.
remove(chipOrValue) Removes a chip by element reference or value string. Returns true if removed.
removeSelected() Removes all currently selected chips.
getValues() Returns an array of all chip values.
getSelectedValues() Returns an array of selected chip values.
clear() Removes all chips.
clearSelection() Deselects all chips without removing them.
selectChip(chip) Selects a specific chip element.
focus() Focuses the ghost input.
dispose() Destroys the component instance.
const chipInputElement = document.querySelector('.chip-input')
const chipInput = coreui.ChipInput.getOrCreateInstance(chipInputElement)

chipInput.add('JavaScript')
chipInput.add('TypeScript')

// eslint-disable-next-line no-console
console.log(chipInput.getValues())

chipInput.remove('JavaScript')
chipInput.clear()

Events

Event Description
input.coreui.chip-input Fired when the inline input value changes. Contains value and relatedTarget.
add.coreui.chip-input Fired before a chip is added. Call event.preventDefault() to cancel.
remove.coreui.chip-input Fired before a chip is removed. Call event.preventDefault() to cancel.
change.coreui.chip-input Fired after any chip is added or removed. Contains values.
select.coreui.chip-input Fired when chip selection changes. Contains selected.
const chipInputElement = document.querySelector('.chip-input')

chipInputElement.addEventListener('add.coreui.chip-input', event => {
  if (event.value.length < 2) {
    event.preventDefault()
  }
})

chipInputElement.addEventListener('input.coreui.chip-input', event => {
  // eslint-disable-next-line no-console
  console.log('Input value:', event.value)
})

chipInputElement.addEventListener('change.coreui.chip-input', event => {
  // eslint-disable-next-line no-console
  console.log('Current values:', event.values)
})

Keyboard behavior

When input is focused

Key Action
Enter Create chip from current input value
, (or separator) Create chip from current input value
Backspace / Delete When input is empty, move focus to the last chip
When cursor is at start, move focus to the last chip
Escape Clear selection, clear input, and blur

When a chip is focused

Key Action
Enter / Space Toggle selection (selectable chips)
Backspace / Delete Remove chip (removable chips)
Move to previous chip
Move to next chip
Home Move to first chip
End Move to last chip

Accessibility

The Bootstrap Chip Input component follows WAI-ARIA patterns to ensure the chip input is fully usable with keyboards and assistive technologies.

  • Associate a <label> with the ghost input for screen readers.
  • Chips are focusable and keyboard navigable when initialized by the plugin.
  • Remove buttons include aria-label="Remove" by default.
  • Selected chips are reflected via .active and aria-selected.
  • Use a descriptive aria-label or <label> on the chip input container to communicate its purpose (e.g., “Add skills” or “Recipients”).

Customizing

CSS variables

Chips inputs use local CSS variables on .chip-input for enhanced real-time customization. Values for the CSS variables are set via Sass, so Sass customization is still supported, too.

--cui-chip-input-min-height: #{$chip-input-min-height};
--cui-chip-input-padding-y: #{$chip-input-padding-y};
--cui-chip-input-padding-x: #{$chip-input-padding-x};
--cui-chip-input-font-size: #{$chip-input-font-size};
--cui-chip-input-bg: #{$chip-input-bg};
--cui-chip-input-color: #{$chip-input-color};
--cui-chip-input-border-width: #{$chip-input-border-width};
--cui-chip-input-border-color: #{$chip-input-border-color};
--cui-chip-input-border-radius: #{$chip-input-border-radius};
--cui-chip-input-gap: #{$chip-input-gap};
--cui-chip-input-transition: #{$chip-input-transition};

SASS variables

$chip-input-min-height:        $input-height;
$chip-input-padding-y:         .25rem;
$chip-input-padding-x:         .75rem;
$chip-input-font-size:         $input-font-size;
$chip-input-bg:                var(--#{$prefix}body-bg);
$chip-input-color:             var(--#{$prefix}body-color);
$chip-input-border-width:      var(--#{$prefix}border-width);
$chip-input-border-color:      var(--#{$prefix}border-color);
$chip-input-border-radius:     var(--#{$prefix}border-radius);
$chip-input-gap:               .375rem;
$chip-input-transition:        $input-transition;

$chip-input-min-height-sm:     $input-height-sm;
$chip-input-padding-y-sm:      .125rem;
$chip-input-padding-x-sm:      .5rem;
$chip-input-font-size-sm:      $input-font-size-sm;
$chip-input-border-radius-sm:  var(--#{$prefix}border-radius-sm);
$chip-input-gap-sm:            .125rem;

$chip-input-min-height-lg:     $input-height-lg;
$chip-input-padding-y-lg:      .375rem;
$chip-input-padding-x-lg:      1rem;
$chip-input-font-size-lg:      $input-font-size-lg;
$chip-input-border-radius-lg:  var(--#{$prefix}border-radius-lg);
$chip-input-gap-lg:            .5rem;