Bootstrap 本身不提供 Tag Selector 组件,需借助 Choices.js 等第三方库或手写逻辑实现;推荐用 Choices.js 结合 Bootstrap 样式类,支持搜索、多选、删除及无障碍访问。

Bootstrap 本身没有内置的 Tag Selector 组件
Bootstrap(包括 v5.x 和 v6 alpha)只提供基础的 form-control、dropdown 和 button-group,不带多选标签输入、动态添加/删除标签、搜索过滤等功能。直接用 form-select 或 form-check 模拟标签选择器,体验差、交互缺失、无法自由输入新标签。
所以实际做法是:用 Bootstrap 的 CSS 类 + 第三方轻量库,或手写最小可行逻辑。
推荐方案:用 Choices.js + Bootstrap 样式兼容
Choices.js 是专注选择器的现代 JS 库,支持单选/多选、搜索、自定义选项、键盘导航,且默认输出语义化 HTML,容易套用 Bootstrap 的 form-control、btn-close 等类。
- 引入
choices.js(CDN 或 npm),确保在 Bootstrap JS 之后加载 - HTML 中用
<select multiple></select>或<input type="text">作为容器,加上class="form-control" - 初始化时关闭自带样式,用
classNames映射 Bootstrap 类名:new Choices(element, { searchEnabled: true, removeItemButton: true, classNames: { containerInner: 'choices__inner form-control', input: 'choices__input form-control', item: 'choices__item badge bg-primary rounded-pill me-1', button: 'btn-close btn-close-white' } }); - 注意:
removeItemButton: true才会渲染删除按钮,否则需手动绑定点击事件
手写简易版:用 input + span 标签 + Bootstrap badge
如果项目不允许引入额外 JS,可基于原生事件 + Bootstrap 样式快速实现“伪标签选择器”:
- HTML 结构保持干净:
<div class="tag-selector"> <input type="text" class="form-control"><div class="tag-list mt-2"></div> </div> - 监听
input的keydown(Enter/Comma)事件,提取值、去重、创建<span class="badge bg-secondary me-1">xxx</span> - 每个
span加data-value属性,点击右侧<button type="button" class="btn-close btn-close-white"></button>删除对应项 - 关键点:
input.value需清空,且要防止空字符串、重复值、前后空格 —— 否则会出现空白 badge 或重复提交 - 不处理键盘焦点管理的话,Tab 键跳过已选标签;如需完整可访问性,必须手动管理
tabindex和aria-*属性
常见踩坑点:样式冲突与事件穿透
Bootstrap 的 .form-control 默认有 padding 和 border-radius,而 choices.js 或手写标签容器常是绝对定位或 flex 布局,容易导致:
- 标签堆叠在 input 下方而非内嵌——解决:给
.tag-list设position: absolute并调整top/z-index,同时 inputpadding-bottom预留空间 - 点击
btn-close触发 input 失焦,导致下拉菜单意外关闭——解决:在button上加event.stopPropagation() - 移动端点击标签后光标仍留在 input,造成误输入——解决:调用
input.blur()或延迟聚焦到 input - 使用
form-select模拟多选时,iOS Safari 不支持multiple的视觉反馈,用户不知道已选中——这根本不是标签选择器,应避免
真正能兼顾体验和维护性的方案,还是让 Choices.js 或 TomSelect 这类库接管逻辑,只借用 Bootstrap 的颜色、间距、圆角等设计 token。自己拼 DOM 容易漏掉键盘操作、屏幕阅读器支持、国际化分隔符这些细节。


















