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.
<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><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.
<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.
<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.
<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.
<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.
<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".
<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.
<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.
Selected chips: None
<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
.activeandaria-selected. - Use a descriptive
aria-labelor<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;