bootstrap-forms

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Bootstrap 5.3 Forms

Bootstrap 5.3 表单

Bootstrap provides comprehensive form styling including controls, layouts, validation states, and input groups.
Bootstrap 提供了全面的表单样式支持,包括控件、布局、验证状态以及输入组。

Form Controls

表单控件

Text Inputs

文本输入框

html
<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control" id="email" placeholder="name@example.com">
</div>

<div class="mb-3">
  <label for="password" class="form-label">Password</label>
  <input type="password" class="form-control" id="password">
</div>
html
<div class="mb-3">
  <label for="email" class="form-label">Email address</label>
  <input type="email" class="form-control" id="email" placeholder="name@example.com">
</div>

<div class="mb-3">
  <label for="password" class="form-label">Password</label>
  <input type="password" class="form-control" id="password">
</div>

Sizing

尺寸设置

To match input size with surrounding elements or emphasize important fields, use sizing classes. Use
.form-control-lg
for hero sections or primary CTAs. Use
.form-control-sm
for compact UIs like toolbars or inline forms.
html
<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">
为了让输入框尺寸与周围元素匹配,或是突出重要字段,可以使用尺寸类。在英雄区块或主要CTA中使用
.form-control-lg
;在工具栏或内联表单这类紧凑UI中使用
.form-control-sm
html
<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 and Readonly

禁用与只读

Use
disabled
for fields users cannot interact with at all. Use
readonly
when values should be visible and selectable but not editable. Use
.form-control-plaintext
with
readonly
to display values without form styling.
html
<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">
使用
disabled
属性设置用户完全无法交互的字段;当值需要可见且可选择但不能编辑时,使用
readonly
属性。结合
readonly
.form-control-plaintext
可以显示不带表单样式的数值。
html
<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">

File Input

文件输入

html
<div class="mb-3">
  <label for="file" class="form-label">Upload file</label>
  <input class="form-control" type="file" id="file">
</div>

<!-- Multiple files -->
<input class="form-control" type="file" multiple>
html
<div class="mb-3">
  <label for="file" class="form-label">Upload file</label>
  <input class="form-control" type="file" id="file">
</div>

<!-- Multiple files -->
<input class="form-control" type="file" multiple>

Color Picker

颜色选择器

html
<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>
html
<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>

Textarea

文本域

html
<div class="mb-3">
  <label for="textarea" class="form-label">Comments</label>
  <textarea class="form-control" id="textarea" rows="3"></textarea>
</div>
html
<div class="mb-3">
  <label for="textarea" class="form-label">Comments</label>
  <textarea class="form-control" id="textarea" rows="3"></textarea>
</div>

Help Text

辅助文本

Use
.form-text
for supplemental instructions. Connect help text to inputs with
aria-describedby
so screen readers announce it when the input is focused:
html
<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>
When an input has both help text and validation feedback, reference both in
aria-describedby
:
html
<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>
使用
.form-text
添加补充说明。通过
aria-describedby
将辅助文本与输入框关联,这样当输入框获得焦点时,屏幕阅读器会朗读该文本:
html
<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
中同时引用两者:
html
<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

选择器

html
<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>

<!-- Multiple select -->
<select class="form-select" multiple>
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>

<!-- Sizing -->
<select class="form-select form-select-lg">...</select>
<select class="form-select form-select-sm">...</select>

<!-- Visible options with size attribute -->
<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>
The
size
attribute displays multiple options without requiring
multiple
selection. Unlike
.form-select-lg
which changes visual scale,
size
controls how many options are visible at once. Use it for small option lists where showing all choices improves usability.
html
<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>

<!-- Multiple select -->
<select class="form-select" multiple>
  <option value="1">One</option>
  <option value="2">Two</option>
  <option value="3">Three</option>
</select>

<!-- Sizing -->
<select class="form-select form-select-lg">...</select>
<select class="form-select form-select-sm">...</select>

<!-- Visible options with size attribute -->
<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
控制的是同时可见的选项数量。在选项列表较短时使用该属性,显示所有选项可以提升易用性。

Datalists

数据列表

Datalists provide autocomplete suggestions for text inputs. They combine the flexibility of free-text input with the convenience of predefined options.
html
<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>
Connect the input to the datalist using the
list
attribute matching the datalist's
id
. Users can type freely or select from suggestions. Datalist styling is browser-native and varies across browsers—Bootstrap's
.form-control
styles the input, but the dropdown appearance is not customizable.
数据列表为文本输入框提供自动补全建议,结合了自由文本输入的灵活性和预定义选项的便捷性。
html
<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>
通过
list
属性将输入框与数据列表关联,
list
的值要与数据列表的
id
匹配。用户可以自由输入,也可以选择建议选项。数据列表的样式是浏览器原生的,不同浏览器会有差异——Bootstrap的
.form-control
会设置输入框的样式,但下拉菜单的外观无法自定义。

Checkboxes and Radios

复选框与单选按钮

Checkboxes

复选框

html
<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>
html
<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>

Indeterminate Checkboxes

不确定状态复选框

Use the indeterminate state for checkboxes representing a "partially checked" condition. This is useful for "select all" patterns where some but not all child items are checked. The state must be set via JavaScript—there is no HTML attribute for it.
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>
对于代表“部分选中”状态的复选框,可以使用不确定状态。这在“全选”场景中非常有用,当部分子项被选中时,全选框就会处于这种状态。该状态必须通过JavaScript设置——没有对应的HTML属性。
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>

Radios

单选按钮

html
<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>
html
<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>

Switches

开关控件

Prefer switches over checkboxes for on/off settings that take effect immediately, like enabling notifications or toggling dark mode. Use checkboxes for multi-select options or when changes require a submit action.
html
<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>
For iOS 17.4+ Safari, add the
switch
attribute to enable native haptic feedback:
html
<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>
对于即时生效的开关设置(比如启用通知或切换深色模式),优先使用开关控件而非复选框;对于多选选项或需要提交后才生效的更改,使用复选框。
html
<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
属性可以启用原生触觉反馈:
html
<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>

Inline

内联排列

html
<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>
html
<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>

Reverse Layout

反向布局

Use
.form-check-reverse
to position the input on the opposite side—label first, checkbox/radio second. This creates a right-aligned input style useful for settings interfaces or RTL layouts.
html
<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>
使用
.form-check-reverse
可以将输入控件放在另一侧——先显示标签,再显示复选框/单选按钮。这种右对齐的输入样式适用于设置界面或RTL布局。
html
<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>

Toggle Buttons

切换按钮

Use
.btn-check
to create button-styled checkboxes and radios. Unlike standard form checks, toggle buttons use
.btn
classes on the label for a button appearance while maintaining checkbox/radio semantics. Use them for segmented controls, filter toggles, and option selectors.
使用
.btn-check
可以创建按钮样式的复选框和单选按钮。与标准表单控件不同,切换按钮在标签上使用
.btn
类,呈现按钮外观,但保留复选框/单选按钮的语义。适用于分段控件、筛选开关和选项选择器。

Checkbox Toggle

复选框切换按钮

html
<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>
html
<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>

Radio Toggle

单选切换按钮

Group radio toggles with the
name
attribute for single-select behavior:
html
<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>
通过
name
属性将单选切换按钮分组,实现单选功能:
html
<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>

Outlined Styles

轮廓样式

Use
.btn-outline-*
for a lighter, bordered appearance:
html
<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>
使用
.btn-outline-*
类可以实现更轻盈的边框样式:
html
<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>

Accessibility

无障碍访问

Toggle buttons are announced by screen readers as "checked"/"not checked" since they are fundamentally checkboxes or radios. This differs from button plugin toggles announced as "button"/"button pressed". Choose based on semantics—use toggle buttons when the control represents a true on/off or selection state.
由于本质上是复选框或单选按钮,屏幕阅读器会将切换按钮读作“已选中”/“未选中”。这与按钮插件的切换按钮不同,后者会被读作“按钮”/“已按下的按钮”。根据语义选择合适的控件:当控件代表真实的开关或选择状态时,使用切换按钮。

Range

范围输入

Range inputs provide a slider control. Use
.form-range
for consistent styling across browsers.
html
<label for="range" class="form-label">Range slider</label>
<input type="range" class="form-range" id="range">

<!-- With min, max, step -->
<input type="range" class="form-range" min="0" max="100" step="5">
范围输入提供滑块控件,使用
.form-range
可以实现跨浏览器的一致样式。
html
<label for="range" class="form-label">Range slider</label>
<input type="range" class="form-range" id="range">

<!-- With min, max, step -->
<input type="range" class="form-range" min="0" max="100" step="5">

Displaying the Current Value

显示当前值

Use the
<output>
element with JavaScript to show the current range value in real-time:
html
<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">
The
oninput
event fires as the slider moves, providing immediate feedback. Place the
<output>
element in the label or nearby for clear association. For more complex scenarios, use a separate event listener instead of inline handlers.
结合
<output>
元素和JavaScript可以实时显示范围输入的当前值:
html
<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>
元素放在标签内或附近,确保关联清晰。对于更复杂的场景,使用独立的事件监听器而非内联处理函数。

Input Groups

输入组

Use input groups to visually attach related elements to form controls. Common patterns include currency symbols, units of measurement, or action buttons alongside inputs.
使用输入组可以将相关元素与表单控件视觉上关联起来。常见的场景包括在输入框旁添加货币符号、计量单位或操作按钮。

Basic

基础用法

html
<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>
html
<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>

With Buttons

带按钮的输入组

html
<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>
html
<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>

Sizing

尺寸设置

html
<div class="input-group input-group-sm">...</div>
<div class="input-group">...</div>
<div class="input-group input-group-lg">...</div>
html
<div class="input-group input-group-sm">...</div>
<div class="input-group">...</div>
<div class="input-group input-group-lg">...</div>

Wrapping Behavior

换行行为

Input groups wrap by default via
flex-wrap: wrap
. To keep all elements on a single line regardless of content width, add
.flex-nowrap
:
html
<div class="input-group flex-nowrap">
  <span class="input-group-text">@</span>
  <input type="text" class="form-control" placeholder="Username">
</div>
输入组默认通过
flex-wrap: wrap
实现换行。若要让所有元素始终在一行显示,无论内容宽度如何,添加
.flex-nowrap
类:
html
<div class="input-group flex-nowrap">
  <span class="input-group-text">@</span>
  <input type="text" class="form-control" placeholder="Username">
</div>

Border Radius Limitations

圆角限制

Hidden elements (using
.d-none
or
display: none
) in the first or last position break border-radius styling on adjacent elements. This is a known Bootstrap limitation. Workaround: move hidden elements outside the input group or use visibility utilities instead when the element needs to remain in the DOM.
输入组的第一个或最后一个元素使用
.d-none
display: none
隐藏时,相邻元素的圆角样式会被破坏。这是Bootstrap的已知限制。解决方法:将隐藏元素移到输入组外,或使用可见性工具类替代。

Segmented Dropdown Buttons

分段下拉按钮

Use
.dropdown-toggle-split
for split button dropdowns within input groups. This creates a separate dropdown trigger alongside a main action button:
html
<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>
在输入组中使用
.dropdown-toggle-split
可以创建分段下拉按钮,在主操作按钮旁单独设置下拉触发器:
html
<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>

Floating Labels

浮动标签

Use floating labels for a cleaner, more compact form design where labels animate into the input on focus. They work best in simple forms like login or signup. Avoid them when you need help text or complex validation messages alongside inputs.
html
<div class="form-floating mb-3">
  <input type="email" class="form-control" id="floatingEmail" placeholder="name@example.com">
  <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>
浮动标签可以实现更简洁紧凑的表单设计,当输入框获得焦点时,标签会动画移动到输入框内。最适合用于登录、注册这类简单表单。当输入框旁需要辅助文本或复杂验证消息时,避免使用浮动标签。
html
<div class="form-floating mb-3">
  <input type="email" class="form-control" id="floatingEmail" placeholder="name@example.com">
  <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>

Input Groups with Floating Labels and Validation

结合输入组、浮动标签与验证

When combining floating labels with input groups and validation, special structure is required. Place
.form-floating
inside
.input-group
, add
.has-validation
to the input group, and place validation feedback outside
.form-floating
but inside
.input-group
:
html
<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>
The
.has-validation
class ensures proper border-radius styling when validation feedback is present. Without it, the input group's visual appearance may break with validation states.
当同时使用浮动标签、输入组和验证时,需要特殊的结构。将
.form-floating
放在
.input-group
内部,为输入组添加
.has-validation
类,并将验证反馈放在
.form-floating
外部但
.input-group
内部:
html
<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 Layout

表单布局

Choose your layout based on form complexity and available space.
根据表单复杂度和可用空间选择合适的布局。

Vertical (Default)

垂直布局(默认)

Use vertical layout for most forms—it's the simplest and works well on mobile. Labels stack above inputs for easy scanning.
html
<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>
大多数表单使用垂直布局——结构最简单,在移动端表现良好。标签堆叠在输入框上方,便于浏览。
html
<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>

Horizontal

水平布局

Use horizontal layout when you have ample width and want a more compact appearance. Best for settings pages or admin panels with many short fields.
html
<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>
当有足够宽度且希望表单更紧凑时,使用水平布局。最适合设置页面或包含多个短字段的管理面板。
html
<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>

Inline

内联布局

html
<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>
html
<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>

Grid Layout

网格布局

html
<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>
html
<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>

Accessibility Essentials

无障碍访问要点

Forms require proper accessibility attributes for screen reader support and WCAG compliance.
表单需要设置合适的无障碍属性,以支持屏幕阅读器并符合WCAG标准。

Labels

标签

Always associate labels with inputs using
for
and
id
attributes:
html
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email">
For visually hidden labels, use
.visually-hidden
:
html
<label for="search" class="visually-hidden">Search</label>
<input type="search" class="form-control" id="search" placeholder="Search...">
始终通过
for
id
属性将标签与输入框关联:
html
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email">
对于视觉上隐藏的标签,使用
.visually-hidden
类:
html
<label for="search" class="visually-hidden">Search</label>
<input type="search" class="form-control" id="search" placeholder="Search...">

Help Text

辅助文本

Connect help text to inputs with
aria-describedby
:
html
<input type="password" class="form-control" id="password" aria-describedby="passwordHelp">
<div id="passwordHelp" class="form-text">Must be 8+ characters.</div>
通过
aria-describedby
将辅助文本与输入框关联:
html
<input type="password" class="form-control" id="password" aria-describedby="passwordHelp">
<div id="passwordHelp" class="form-text">Must be 8+ characters.</div>

Validation States

验证状态

Mark invalid fields for assistive technology:
html
<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>
为辅助技术标记无效字段:
html
<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>

Required Fields

必填字段

html
<input type="text" class="form-control" required aria-required="true">
html
<input type="text" class="form-control" required aria-required="true">

Validation

表单验证

Browser Default

浏览器默认验证

html
<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>
html
<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>

Validation States

验证状态

html
<!-- Valid -->
<input type="text" class="form-control is-valid">
<div class="valid-feedback">Looks good!</div>

<!-- Invalid -->
<input type="text" class="form-control is-invalid">
<div class="invalid-feedback">Please provide a valid value.</div>
html
<!-- Valid -->
<input type="text" class="form-control is-valid">
<div class="valid-feedback">Looks good!</div>

<!-- Invalid -->
<input type="text" class="form-control is-invalid">
<div class="invalid-feedback">Please provide a valid value.</div>

Validation Tooltips

验证提示框

Use
.valid-tooltip
and
.invalid-tooltip
as alternatives to feedback messages when you want positioned tooltip-style validation. Tooltips appear as floating messages positioned absolutely, requiring the parent element to have
position: relative
:
html
<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>
Tooltips are useful when feedback messages would disrupt form layout or when you want a more prominent visual indicator. Use them consistently within a form—avoid mixing tooltips and feedback messages.
当希望验证反馈以提示框样式显示时,可以使用
.valid-tooltip
.invalid-tooltip
替代普通反馈消息。提示框是绝对定位的浮动消息,要求父元素设置
position: relative
html
<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>
当反馈消息会破坏表单布局,或是需要更醒目的视觉提示时,适合使用提示框。在同一个表单中要保持一致,避免同时使用提示框和普通反馈消息。

Common Mistakes

常见错误

MistakeProblemFix
Using placeholder as labelNot accessible, disappears on inputAlways use
<label>
elements
Missing
novalidate
with custom validation
Browser shows default + custom feedbackAdd
novalidate
to
<form>
Forgetting
.has-validation
on input groups
Border radius breaks with validationAdd
.has-validation
to
.input-group
Labels without
for
attribute
Screen readers can't associate labelMatch
for
with input
id
Missing
aria-describedby
for help text
Help text not announcedConnect with
aria-describedby
Omitting
aria-invalid="true"
Screen readers miss error stateAdd
aria-invalid
with
.is-invalid
Using
display: none
on first/last input group item
Border radius breaks on adjacent elementsUse
.visually-hidden
or move outside group
See
references/validation-approaches.md
for validation method comparison and
references/accessibility-checklist.md
for complete accessibility requirements.
错误问题修复方案
使用占位符作为标签无障碍性差,输入时会消失始终使用
<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
了解完整的无障碍访问要求。

Additional Resources

额外资源

Reference Files

参考文件

  • references/form-reference.md
    - Complete form class reference
  • references/validation-approaches.md
    - Browser vs custom vs server-side validation comparison
  • references/accessibility-checklist.md
    - Required attributes and testing procedures
  • references/form-reference.md
    - 完整的表单类参考
  • references/validation-approaches.md
    - 浏览器验证、自定义验证与服务端验证的对比
  • references/accessibility-checklist.md
    - 必填属性与测试流程

Example Files

示例文件

  • examples/validation-form.html
    - Form validation patterns
  • examples/floating-labels-form.html
    - Signup and login forms with floating labels
  • examples/horizontal-form.html
    - Horizontal layouts, sizing, radios, readonly display
  • examples/inline-search-form.html
    - Navbar search, filters, toolbars, newsletter forms
  • examples/toggle-buttons.html
    - Checkbox and radio toggle buttons, outlined styles
  • examples/accessibility-patterns.html
    - Accessible forms with ARIA attributes
  • 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属性的无障碍表单