关于 bootstrap-forms
为前端开发者提供 Bootstrap 5.3 表单组件与布局的参考技能,涵盖控件、验证和无障碍实践。
主要功能
- 01表单控件与尺寸样式
- 02选择框、数据列表与开关
- 03输入组和浮动标签
- 04纵向、横向及网格布局
- 05验证状态与无障碍属性
适用场景
- 01构建登录或注册表单
- 02设计设置页和管理面板
- 03实现表单验证反馈
- 04检查屏幕阅读器支持
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sjnims/ bootstrap-expert --skill bootstrap-forms安装后在 Claude Code 中输入/bootstrap-forms确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/accessibility-patterns.htmlfloating-labels-form.htmlhorizontal-form.htmlinline-search-form.htmltoggle-buttons.htmlvalidation-form.htmlreferences/accessibility-checklist.mdform-reference.mdvalidation-approaches.md详细介绍
Bootstrap 5.3 表单
Bootstrap 提供全面的表单样式,包括控件、布局、验证状态和输入组。
表单控件
文本输入框
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" placeholder="[email protected]">
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password">
</div>
尺寸
要使输入框尺寸与周围元素匹配,或突出重要字段,请使用尺寸类。对于主视觉区域或主要 CTA,请使用 .form-control-lg。对于工具栏或内联表单等紧凑型 UI,请使用 .form-control-sm。
<input class="form-control form-control-lg" type="text" placeholder="Large input">
<input class="form-control" type="text" placeholder="Default input">
<input class="form-control form-control-sm" type="text" placeholder="Small input">
禁用和只读
对于用户完全无法交互的字段,请使用 disabled。当值应可见且可选中,但不可编辑时,请使用 readonly。使用 .form-control-plaintext 和 readonly 可在不显示表单样式的情况下展示值。
<input class="form-control" type="text" disabled value="Disabled input">
<input class="form-control" type="text" readonly value="Readonly input">
<input class="form-control-plaintext" type="text" readonly value="Readonly plain text">
文件输入框
<div class="mb-3">
<label for="file" class="form-label">Upload file</label>
<input class="form-control" type="file" id="file">
</div>
<input class="form-control" type="file" multiple>
颜色选择器
<div class="mb-3">
<label for="color" class="form-label">Color picker</label>
<input type="color" class="form-control form-control-color" id="color" value="#0d6efd">
</div>
文本区域
<div class="mb-3">
<label for="textarea" class="form-label">Comments</label>
<textarea class="form-control" id="textarea" rows="3"></textarea>
</div>
帮助文本
使用 .form-text 提供补充说明。通过 aria-describedby 将帮助文本与输入框关联,以便屏幕阅读器在输入框获得焦点时读出说明:
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" aria-describedby="passwordHelp">
<div id="passwordHelp" class="form-text">Must be 8+ characters with one uppercase letter.</div>
</div>
当输入框同时有帮助文本和验证反馈时,请在 aria-describedby 中引用二者:
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control is-invalid" id="email"
aria-describedby="emailHelp emailError" aria-invalid="true">
<div id="emailHelp" class="form-text">We'll never share your email.</div>
<div id="emailError" class="invalid-feedback">Please enter a valid email address.</div>
</div>
选择框
<select class="form-select">
<option selected>Choose an option</option>
<option value="1">Option One</option>
<option value="2">Option Two</option>
<option value="3">Option Three</option>
</select>
<select class="form-select" multiple>
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
<select class="form-select form-select-lg">...</select>
<select class="form-select form-select-sm">...</select>
<select class="form-select" size="3">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
</select>
size 属性无需启用 multiple 选择即可显示多个选项。与改变视觉尺寸的 .form-select-lg 不同,size 控制一次可见的选项数量。对于选项较少、显示所有选项更便于使用的列表,请使用此属性。
数据列表
数据列表为文本输入框提供自动完成建议。它结合了自由文本输入的灵活性和预定义选项的便利性。
<label for="browser" class="form-label">Choose a browser</label>
<input class="form-control" list="browsers" id="browser" placeholder="Type to search...">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
<option value="Edge">
<option value="Opera">
</datalist>
使用与数据列表 id 匹配的 list 属性将输入框与数据列表关联。用户可以自由输入,也可以从建议中选择。数据列表的样式由浏览器原生控制,并因浏览器而异——Bootstrap 的 .form-control 会为输入框设置样式,但下拉菜单的外观不可自定义。
复选框和单选按钮
复选框
<div class="form-check">
<input class="form-check-input" type="checkbox" id="check1">
<label class="form-check-label" for="check1">Default checkbox</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="check2" checked>
<label class="form-check-label" for="check2">Checked checkbox</label>
</div>
不确定状态的复选框
对于表示“部分选中”状态的复选框,请使用不确定状态。这适用于“全选”模式,其中部分子项已选中,但并非全部选中。此状态必须通过 JavaScript 设置——HTML 没有对应的属性。
<div class="form-check">
<input class="form-check-input" type="checkbox" id="checkIndeterminate">
<label class="form-check-label" for="checkIndeterminate">Select all items</label>
</div>
<script>
document.getElementById('checkIndeterminate').indeterminate = true;
</script>
单选按钮
<div class="form-check">
<input class="form-check-input" type="radio" name="radios" id="radio1" checked>
<label class="form-check-label" for="radio1">First radio</label>
</div>
<div class="form-check">
<input class="form-check-input" type="radio" name="radios" id="radio2">
<label class="form-check-label" for="radio2">Second radio</label>
</div>
开关
对于立即生效的开/关设置(例如启用通知或切换深色模式),建议使用开关而非复选框。对于多选选项,或需要提交后才生效的更改,请使用复选框。
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="switch1">
<label class="form-check-label" for="switch1">Default switch</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="switch2" checked>
<label class="form-check-label" for="switch2">Checked switch</label>
</div>
对于 iOS 17.4+ Safari,请添加 switch 属性以启用原生触觉反馈:
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="nativeSwitch" switch>
<label class="form-check-label" for="nativeSwitch">Native haptics (iOS 17.4+)</label>
</div>
内联
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline1">
<label class="form-check-label" for="inline1">1</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input" type="checkbox" id="inline2">
<label class="form-check-label" for="inline2">2</label>
</div>
反向布局
使用 .form-check-reverse 将输入控件放在另一侧——标签在前,复选框或单选按钮在后。这会创建输入控件右对齐的样式,适用于设置界面或 RTL 布局。
<div class="form-check form-check-reverse">
<input class="form-check-input" type="checkbox" id="reverseCheck">
<label class="form-check-label" for="reverseCheck">Reverse checkbox</label>
</div>
<div class="form-check form-check-reverse">
<input class="form-check-input" type="radio" name="reverseRadios" id="reverseRadio1">
<label class="form-check-label" for="reverseRadio1">First reverse radio</label>
</div>
切换按钮
使用 .btn-check 创建按钮样式的复选框和单选按钮。与标准表单选项不同,切换按钮会在标签上使用 .btn 类来呈现按钮外观,同时保留复选框或单选按钮的语义。适用于分段控件、筛选器切换和选项选择器。
复选框切换按钮
<input type="checkbox" class="btn-check" id="btn-check" autocomplete="off">
<label class="btn btn-primary" for="btn-check">Single toggle</label>
<input type="checkbox" class="btn-check" id="btn-check-2" checked autocomplete="off">
<label class="btn btn-primary" for="btn-check-2">Checked</label>
<input type="checkbox" class="btn-check" id="btn-check-3" disabled autocomplete="off">
<label class="btn btn-primary" for="btn-check-3">Disabled</label>
单选按钮切换
为单选切换按钮设置相同的 name 属性,以实现单选行为:
<input type="radio" class="btn-check" name="options" id="option1" autocomplete="off" checked>
<label class="btn btn-secondary" for="option1">Checked</label>
<input type="radio" class="btn-check" name="options" id="option2" autocomplete="off">
<label class="btn btn-secondary" for="option2">Radio</label>
<input type="radio" class="btn-check" name="options" id="option3" autocomplete="off">
<label class="btn btn-secondary" for="option3">Radio</label>
轮廓样式
使用 .btn-outline-* 呈现更轻盈的边框外观:
<input type="checkbox" class="btn-check" id="btn-outlined" autocomplete="off">
<label class="btn btn-outline-primary" for="btn-outlined">Toggle</label>
<input type="radio" class="btn-check" name="opts" id="success" autocomplete="off" checked>
<label class="btn btn-outline-success" for="success">Success</label>
<input type="radio" class="btn-check" name="opts" id="danger" autocomplete="off">
<label class="btn btn-outline-danger" for="danger">Danger</label>
无障碍
屏幕阅读器会将切换按钮读作“已选中”或“未选中”,因为它们本质上是复选框或单选按钮。这与按钮插件切换不同,后者会被读作“按钮”或“按钮已按下”。请根据语义选择——当控件表示真正的开/关或选择状态时,使用切换按钮。
范围
范围输入框提供滑块控件。使用 .form-range 可确保不同浏览器中的样式一致。
<label for="range" class="form-label">Range slider</label>
<input type="range" class="form-range" id="range">
<input type="range" class="form-range" min="0" max="100" step="5">
显示当前值
使用 <output> 元素和 JavaScript 实时显示当前范围值:
<label for="volumeRange" class="form-label">
Volume: <output id="volumeValue">50</output>
</label>
<input type="range" class="form-range" id="volumeRange"
min="0" max="100" value="50"
oninput="document.getElementById('volumeValue').textContent = this.value">
滑块移动时会触发 oninput 事件,立即提供反馈。将 <output> 元素放在标签内或附近,以建立清晰的关联。对于更复杂的场景,请使用单独的事件监听器,而不是内联处理程序。
输入组
使用输入组将相关元素在视觉上连接到表单控件。常见模式包括货币符号、计量单位,或与输入框并排显示的操作按钮。
基本用法
<div class="input-group mb-3">
<span class="input-group-text">@</span>
<input type="text" class="form-control" placeholder="Username">
</div>
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Email">
<span class="input-group-text">@example.com</span>
</div>
<div class="input-group mb-3">
<span class="input-group-text">$</span>
<input type="text" class="form-control" placeholder="Amount">
<span class="input-group-text">.00</span>
</div>
带按钮
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Search...">
<button class="btn btn-outline-secondary" type="button">Search</button>
</div>
<div class="input-group mb-3">
<button class="btn btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown">
Dropdown
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#">Action</a></li>
</ul>
<input type="text" class="form-control">
</div>
尺寸
<div class="input-group input-group-sm">...</div>
<div class="input-group">...</div>
<div class="input-group input-group-lg">...</div>
换行行为
输入组默认通过 flex-wrap: wrap 换行。若要无论内容宽度如何都让所有元素保持在同一行,请添加 .flex-nowrap:
<div class="input-group flex-nowrap">
<span class="input-group-text">@</span>
<input type="text" class="form-control" placeholder="Username">
</div>
圆角限制
位于首位或末位的隐藏元素(使用 .d-none 或 display: none)会破坏相邻元素的圆角样式。这是 Bootstrap 的已知限制。解决方法:将隐藏元素移到输入组外,或者在元素需要保留在 DOM 中时改用可见性工具类。
分段下拉按钮
在输入组中使用 .dropdown-toggle-split 创建分段下拉按钮。这样会在主操作按钮旁边创建单独的下拉触发器:
<div class="input-group">
<button type="button" class="btn btn-outline-secondary">Action</button>
<button type="button" class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split"
data-bs-toggle="dropdown" aria-expanded="false">
<span class="visually-hidden">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="#">Option 1</a></li>
<li><a class="dropdown-item" href="#">Option 2</a></li>
</ul>
<input type="text" class="form-control" placeholder="Enter value">
</div>
浮动标签
使用浮动标签打造更简洁紧凑的表单设计,让标签在输入框获得焦点时浮动。它们最适合登录或注册等简单表单。如果需要在输入框旁显示帮助文本或复杂的验证消息,请避免使用。
<div class="form-floating mb-3">
<input type="email" class="form-control" id="floatingEmail" placeholder="[email protected]">
<label for="floatingEmail">Email address</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password">
<label for="floatingPassword">Password</label>
</div>
<div class="form-floating">
<textarea class="form-control" placeholder="Leave a comment" id="floatingTextarea"></textarea>
<label for="floatingTextarea">Comments</label>
</div>
带浮动标签和验证的输入组
将浮动标签与输入组和验证结合使用时,需要采用特殊结构。将 .form-floating 放在 .input-group 内,为输入组添加 .has-validation,并将验证反馈放在 .form-floating 外、.input-group 内:
<div class="input-group has-validation">
<span class="input-group-text">@</span>
<div class="form-floating is-invalid">
<input type="text" class="form-control is-invalid" id="floatingUsername"
placeholder="Username" required>
<label for="floatingUsername">Username</label>
</div>
<div class="invalid-feedback">Please choose a username.</div>
</div>
.has-validation 类可确保存在验证反馈时正确显示圆角样式。若不添加该类,输入组在验证状态下的视觉样式可能会出现问题。
表单布局
请根据表单的复杂程度和可用空间选择布局。
垂直布局(默认)
大多数表单使用垂直布局即可,它最简单,也适用于移动设备。标签堆叠在输入框上方,便于快速浏览。
<form>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email">
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
水平布局
当宽度充足且希望布局更紧凑时,使用水平布局。它最适合包含许多简短字段的设置页面或管理面板。
<form>
<div class="row mb-3">
<label for="email" class="col-sm-2 col-form-label">Email</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="email">
</div>
</div>
<div class="row">
<div class="col-sm-10 offset-sm-2">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
内联布局
<form class="row row-cols-lg-auto g-3 align-items-center">
<div class="col-12">
<input type="text" class="form-control" placeholder="Username">
</div>
<div class="col-12">
<select class="form-select">
<option selected>Choose...</option>
</select>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
网格布局
<form>
<div class="row g-3">
<div class="col-md-6">
<label for="firstName" class="form-label">First name</label>
<input type="text" class="form-control" id="firstName">
</div>
<div class="col-md-6">
<label for="lastName" class="form-label">Last name</label>
<input type="text" class="form-control" id="lastName">
</div>
<div class="col-12">
<label for="address" class="form-label">Address</label>
<input type="text" class="form-control" id="address">
</div>
<div class="col-md-6">
<label for="city" class="form-label">City</label>
<input type="text" class="form-control" id="city">
</div>
<div class="col-md-4">
<label for="state" class="form-label">State</label>
<select id="state" class="form-select">
<option selected>Choose...</option>
</select>
</div>
<div class="col-md-2">
<label for="zip" class="form-label">Zip</label>
<input type="text" class="form-control" id="zip">
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
无障碍基础
表单需要正确的无障碍属性,以支持屏幕阅读器并符合 WCAG 要求。
标签
始终使用 for 和 id 属性将标签与输入框关联:
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email">
对于视觉上隐藏的标签,请使用 .visually-hidden:
<label for="search" class="visually-hidden">Search</label>
<input type="search" class="form-control" id="search" placeholder="Search...">
帮助文本
使用 aria-describedby 将帮助文本与输入框关联:
<input type="password" class="form-control" id="password" aria-describedby="passwordHelp">
<div id="passwordHelp" class="form-text">Must be 8+ characters.</div>
验证状态
为无效字段添加标记,以便辅助技术识别:
<input type="email" class="form-control is-invalid" aria-invalid="true" aria-describedby="emailError">
<div id="emailError" class="invalid-feedback">Please enter a valid email.</div>
必填字段
<input type="text" class="form-control" required aria-required="true">
验证
浏览器默认验证
<form class="row g-3 needs-validation" novalidate>
<div class="col-md-6">
<label for="validationCustom01" class="form-label">First name</label>
<input type="text" class="form-control" id="validationCustom01" required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please provide a first name.</div>
</div>
<div class="col-12">
<button class="btn btn-primary" type="submit">Submit form</button>
</div>
</form>
<script>
// JavaScript for validation
(function () {
'use strict'
var forms = document.querySelectorAll('.needs-validation')
Array.prototype.slice.call(forms).forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
验证状态
<input type="text" class="form-control is-valid">
<div class="valid-feedback">Looks good!</div>
<input type="text" class="form-control is-invalid">
<div class="invalid-feedback">Please provide a valid value.</div>
验证工具提示
如果希望使用定位的工具提示样式验证来替代反馈消息,请使用 .valid-tooltip 和 .invalid-tooltip。工具提示会以浮动消息的形式绝对定位显示,因此父元素需要设置 position: relative:
<div class="col-md-4 position-relative">
<label for="city" class="form-label">City</label>
<input type="text" class="form-control is-invalid" id="city" required>
<div class="valid-tooltip">Looks good!</div>
<div class="invalid-tooltip">Please provide a valid city.</div>
</div>
当反馈消息会打乱表单布局,或需要更醒目的视觉提示时,工具提示很有用。请在表单中保持一致使用,避免混用工具提示和反馈消息。
常见错误
| 错误 | 问题 | 修正方法 |
|---|---|---|
| 使用占位符作为标签 | 不具备无障碍访问性,输入内容后会消失 | 始终使用 <label> 元素 |
使用自定义验证时缺少 novalidate | 浏览器会同时显示默认反馈和自定义反馈 | 在 <form> 中添加 novalidate |
忘记在输入组上添加 .has-validation | 验证时边框圆角会显示异常 | 在 .input-group 上添加 .has-validation |
标签缺少 for 属性 | 屏幕阅读器无法将标签与输入框关联 | 使 for 与输入框的 id 匹配 |
帮助文本缺少 aria-describedby | 屏幕阅读器不会朗读帮助文本 | 使用 aria-describedby 关联 |
省略 aria-invalid="true" | 屏幕阅读器无法识别错误状态 | 与 .is-invalid 一起添加 aria-invalid |
对输入组中的首项或末项使用 display: none | 相邻元素的边框圆角会显示异常 | 使用 .visually-hidden,或将其移到组外 |
请参阅 references/validation-approaches.md,了解验证方法对比;请参阅 references/accessibility-checklist.md,了解完整的无障碍访问要求。
其他资源
参考文件
references/form-reference.md- 完整的表单类参考references/validation-approaches.md- 浏览器验证、自定义验证和服务器端验证的对比references/accessibility-checklist.md- 必需属性和测试流程
示例文件
examples/validation-form.html- 表单验证模式examples/floating-labels-form.html- 带浮动标签的注册和登录表单examples/horizontal-form.html- 水平布局、尺寸、单选按钮、只读显示examples/inline-search-form.html- 导航栏搜索、筛选器、工具栏、新闻简报表单examples/toggle-buttons.html- 复选框和单选按钮切换按钮、轮廓样式examples/accessibility-patterns.html- 带 ARIA 属性的无障碍表单