Skip to component content

Compose the ready Input, Textarea, Native Select, Checkbox, Radio Group, and Switch controls into accessible, label-first fields using Bootstrap-native validation and semantic grouping.

Pair a visible label with helper text below the control.

Usage

Use .field as the smallest repeatable form unit inside a Form: one visible label, one control or control group, and the helper or error text that explains it. Keep the label before the control, connect helper or validation text with aria-describedby, and place feedback directly under the control it describes.

Mark required, readonly, disabled, and invalid states on the native control so Bootstrap form styles and browser behavior stay aligned. When validation fails, show the invalid state on both the field context and the affected control, then keep the message specific enough to tell the user how to recover.

Use field groups for stacked fields that belong to the same form section, and use a fieldset with a legend when multiple controls answer one larger question. Keep descriptions visible when they change the user's decision; avoid hiding important form instructions behind tooltips.

Full example

Build one compact native form from semantic fieldsets and grouped controls. Bootstrap validation uses novalidate, needs-validation, and standard field-level feedback.

Field
Deployment
Configure where and how this build ships.
Enter a project name.
Runs before every deploy.
Notifications
Who to notify when this deploy finishes.
Shown in the deploy log for teammates.
<form class="field-form needs-validation" novalidate>
  <fieldset class="field-fieldset">
    <legend class="field-legend">Deployment</legend>
    <div class="field-description form-text">Configure where and how this build ships.</div>
    <div class="field-group">
      <div class="field">
        <label class="form-label" for="field-full-project">
          Project name
          <span class="text-danger">*</span>
        </label>
        <input class="form-control" id="field-full-project" type="text" placeholder="marketing-site" required aria-describedby="field-full-project-error">
        <div class="field-error invalid-feedback" id="field-full-project-error">Enter a project name.</div>
      </div>
      <div class="field">
        <label class="form-label" for="field-full-build">Build command</label>
        <input class="form-control" id="field-full-build" type="text" placeholder="npm run build" aria-describedby="field-full-build-description">
        <div class="field-description form-text" id="field-full-build-description">Runs before every deploy.</div>
      </div>
    </div>
    <div class="field-group">
      <div class="d-flex flex-wrap gap-3">
        <div class="field flex-fill">
          <label class="form-label" for="field-full-region">Region</label>
          <select class="form-select" id="field-full-region" data-selected="us-east">
            <option value="us-east" selected>US East</option>
            <option value="eu-west">EU West</option>
            <option value="ap-southeast">AP Southeast</option>
          </select>
        </div>
        <div class="field flex-fill">
          <label class="form-label" for="field-full-size">Instance size</label>
          <select class="form-select" id="field-full-size" data-selected="medium">
            <option value="small">Small</option>
            <option value="medium" selected>Medium</option>
            <option value="large">Large</option>
          </select>
        </div>
        <div class="field flex-fill">
          <label class="form-label" for="field-full-replicas">Replicas</label>
          <input class="form-control" id="field-full-replicas" type="text" value="2">
        </div>
      </div>
    </div>
  </fieldset>
  <hr aria-hidden="true">
  <fieldset class="field-fieldset">
    <legend class="field-legend">Notifications</legend>
    <div class="field-description form-text">Who to notify when this deploy finishes.</div>
    <div class="field-group">
      <div class="field">
        <div class="form-check form-switch">
          <input class="form-check-input" type="checkbox" role="switch" id="field-full-notify" checked>
          <label class="form-check-label" for="field-full-notify">Notify the whole channel</label>
        </div>
      </div>
    </div>
    <div class="field-group">
      <div class="field">
        <label class="form-label" for="field-full-notes">Notes</label>
        <textarea class="form-control" id="field-full-notes" rows="3" placeholder="Add context for teammates watching the deploy log." aria-describedby="field-full-notes-description"></textarea>
        <div class="field-description form-text" id="field-full-notes-description">Shown in the deploy log for teammates.</div>
      </div>
    </div>
  </fieldset>
  <div class="d-flex gap-2">
    <button class="btn btn-primary" type="submit">Deploy</button>
    <button class="btn btn-outline-secondary" type="reset">Cancel</button>
  </div>
</form>

Basic field

Place helper text next to its control and connect their IDs with aria-describedby for assistive relationships.

Field
Shown across the workspace and on shared links.
<div class="field">
  <label class="form-label" for="field-basic-name">Display name</label>
  <input class="form-control" id="field-basic-name" type="text" placeholder="Ada Lovelace" aria-describedby="field-basic-name-description">
  <div class="field-description form-text" id="field-basic-name-description">Shown across the workspace and on shared links.</div>
</div>

Input with validation error

Set data-invalid="true" on the field, aria-invalid="true" on the control, and render linked feedback directly below it.

Field
Slugs can only contain lowercase letters, numbers, and hyphens.
<div class="field" data-invalid="true">
  <label class="form-label" for="field-invalid-slug">Workspace slug</label>
  <input class="form-control is-invalid" id="field-invalid-slug" type="text" value="my workspace" aria-invalid="true" aria-describedby="field-invalid-slug-error">
  <div class="field-error invalid-feedback" id="field-invalid-slug-error">Slugs can only contain lowercase letters, numbers, and hyphens.</div>
</div>

Disabled field

Keep the label and helper text visible when a field is temporarily unavailable by using the control's native disabled state.

Field
This value is maintained centrally and can't be edited in this state.
<div class="field">
  <label class="form-label" for="field-disabled-project">Read-only project</label>
  <input class="form-control" id="field-disabled-project" type="text" value="release-automation" disabled aria-describedby="field-disabled-project-description">
  <div class="field-description form-text" id="field-disabled-project-description">This value is maintained centrally and can&#39;t be edited in this state.</div>
</div>

Field group

Group related labeled controls with a consistent gap while preserving each control's accessible relationships.

Field
<div class="field-group">
  <div class="field">
    <label class="form-label" for="field-group-first">First name</label>
    <input class="form-control" id="field-group-first" type="text" placeholder="Ada">
  </div>
  <div class="field">
    <label class="form-label" for="field-group-last">Last name</label>
    <input class="form-control" id="field-group-last" type="text" placeholder="Lovelace">
  </div>
</div>

Textarea

Multiline controls retain the same label, spacing, and linked helper-text contract as single-line inputs.

Field
Shown to your team in the changelog.
<div class="field">
  <label class="form-label" for="field-textarea-notes">Release notes</label>
  <textarea class="form-control" id="field-textarea-notes" rows="3" placeholder="What changed in this deploy?" aria-describedby="field-textarea-notes-description"></textarea>
  <div class="field-description form-text" id="field-textarea-notes-description">Shown to your team in the changelog.</div>
</div>

Native Select

Use native select markup with the same visible-label and helper-text flow as other fields.

Field
Used to schedule your deploy window.
<div class="field">
  <label class="form-label" for="field-select-timezone">Time zone</label>
  <select class="form-select" id="field-select-timezone" aria-describedby="field-select-timezone-description" data-selected="et">
    <option value="pt">Pacific Time</option>
    <option value="et" selected>Eastern Time</option>
    <option value="cet">Central European Time</option>
  </select>
  <div class="field-description form-text" id="field-select-timezone-description">Used to schedule your deploy window.</div>
</div>

Fieldset

A native <fieldset> with a <legend> and optional description groups related controls semantically.

Field
Notifications
Choose what you want to hear about.
<fieldset class="field-fieldset">
  <legend class="field-legend">Notifications</legend>
  <div class="field-description form-text">Choose what you want to hear about.</div>
  <div class="field-group">
    <div class="field">
      <div class="form-check form-switch">
        <input class="form-check-input" type="checkbox" role="switch" id="field-fieldset-product" checked>
        <label class="form-check-label" for="field-fieldset-product">Product updates</label>
      </div>
    </div>
    <div class="field">
      <div class="form-check form-switch">
        <input class="form-check-input" type="checkbox" role="switch" id="field-fieldset-billing" checked>
        <label class="form-check-label" for="field-fieldset-billing">Billing alerts</label>
      </div>
    </div>
    <div class="field">
      <div class="form-check form-switch">
        <input class="form-check-input" type="checkbox" role="switch" id="field-fieldset-digest">
        <label class="form-check-label" for="field-fieldset-digest">Weekly digest</label>
      </div>
    </div>
  </div>
</fieldset>

Fieldset with a nested row

Side-by-side labeled controls can sit inside the same semantic group without changing their individual field contracts.

Field
Support contact
Who should we reach out to about this project?
<fieldset class="field-fieldset">
  <legend class="field-legend">Support contact</legend>
  <div class="field-description form-text">Who should we reach out to about this project?</div>
  <div class="field-group">
    <div class="field">
      <label class="form-label" for="field-contact-name">Contact name</label>
      <input class="form-control" id="field-contact-name" type="text" placeholder="Grace Hopper">
    </div>
    <div class="d-flex flex-wrap gap-3">
      <div class="field flex-fill">
        <label class="form-label" for="field-contact-email">Email</label>
        <input class="form-control" id="field-contact-email" type="text" placeholder="grace@example.com">
      </div>
      <div class="field flex-fill">
        <label class="form-label" for="field-contact-phone">Phone</label>
        <input class="form-control" id="field-contact-phone" type="text" placeholder="+1 (555) 010-0100">
      </div>
    </div>
  </div>
</fieldset>

Checkbox group

Each checkbox carries its own visible label, so related choices can be grouped directly when no additional helper text is needed.

Field
Visible dashboard widgets
Choose what shows on your team's overview.
Preferences carry over to any device you sign into.
<div class="vstack gap-3">
  <fieldset class="field-fieldset">
    <legend class="field-legend">Visible dashboard widgets</legend>
    <div class="field-description form-text">Choose what shows on your team&#39;s overview.</div>
    <div class="field-group">
      <div class="field">
        <div class="form-check">
          <input class="form-check-input" type="checkbox" id="field-widget-revenue" checked>
          <label class="form-check-label" for="field-widget-revenue">Revenue</label>
        </div>
      </div>
      <div class="field">
        <div class="form-check">
          <input class="form-check-input" type="checkbox" id="field-widget-users" checked>
          <label class="form-check-label" for="field-widget-users">Active users</label>
        </div>
      </div>
      <div class="field">
        <div class="form-check">
          <input class="form-check-input" type="checkbox" id="field-widget-errors">
          <label class="form-check-label" for="field-widget-errors">Error rate</label>
        </div>
      </div>
      <div class="field">
        <div class="form-check">
          <input class="form-check-input" type="checkbox" id="field-widget-deploys">
          <label class="form-check-label" for="field-widget-deploys">Deploy history</label>
        </div>
      </div>
    </div>
  </fieldset>
  <div class="field">
    <div class="form-check">
      <input class="form-check-input" type="checkbox" id="field-sync" checked aria-describedby="field-sync-description">
      <label class="form-check-label" for="field-sync">Sync settings across devices</label>
      <div class="form-text" id="field-sync-description">Preferences carry over to any device you sign into.</div>
    </div>
  </div>
</div>

Radio group

Radio Group renders a complete native fieldset and can sit beside other labeled field contracts.

Field
Compute tier
<div class="field">
  <fieldset class="radio-group">
    <legend class="form-label">Compute tier</legend>
    <div class="form-check">
      <input class="form-check-input" type="radio" name="compute-tier" id="field-tier-standard" value="standard" checked>
      <label class="form-check-label" for="field-tier-standard">Standard ($0.02/min)</label>
    </div>
    <div class="form-check">
      <input class="form-check-input" type="radio" name="compute-tier" id="field-tier-performance" value="performance">
      <label class="form-check-label" for="field-tier-performance">Performance ($0.05/min)</label>
    </div>
    <div class="form-check">
      <input class="form-check-input" type="radio" name="compute-tier" id="field-tier-turbo" value="turbo">
      <label class="form-check-label" for="field-tier-turbo">Turbo ($0.12/min)</label>
    </div>
  </fieldset>
</div>

Switch

A switch with an inline label and no helper text is a complete compact field contract by itself.

Field
<div class="field">
  <div class="form-check form-switch">
    <input class="form-check-input" type="checkbox" role="switch" id="field-2fa">
    <label class="form-check-label" for="field-2fa">Require two-factor sign-in</label>
  </div>
</div>

Field group with a separator

Use a documented Separator between grouped sections to create a clear transition in long option sets.

Field
Usage alerts
Notified as this project approaches its monthly usage limit.
<fieldset class="field-fieldset">
  <legend class="field-legend">Usage alerts</legend>
  <div class="field-description form-text">Notified as this project approaches its monthly usage limit.</div>
  <div class="field-group">
    <div class="field">
      <div class="form-check">
        <input class="form-check-input" type="checkbox" id="field-usage-80" checked>
        <label class="form-check-label" for="field-usage-80">Notify at 80% quota</label>
      </div>
    </div>
    <div class="field">
      <div class="form-check">
        <input class="form-check-input" type="checkbox" id="field-usage-100" checked>
        <label class="form-check-label" for="field-usage-100">Notify at 100% quota</label>
      </div>
    </div>
  </div>
</fieldset>

RTL

Spacing and label/helper relationships remain stable across Arabic and Hebrew RTL examples, with English as the LTR comparison.

يظهر في لوحة النشر وفي روابط الفريق.
تُظهر هذه الملاحظات فرق الدعم قبل الإقلاع.
<div class="w-100" dir="rtl">
  <div class="field">
    <label class="form-label" for="field-rtl-arabic-project">اسم المشروع</label>
    <input class="form-control" id="field-rtl-arabic-project" type="text" placeholder="marketing-site" aria-describedby="field-rtl-arabic-project-description">
    <div class="field-description form-text" id="field-rtl-arabic-project-description">يظهر في لوحة النشر وفي روابط الفريق.</div>
  </div>
  <div class="field">
    <label class="form-label" for="field-rtl-arabic-notes">ملاحظات</label>
    <textarea class="form-control" id="field-rtl-arabic-notes" rows="3" placeholder="أضف ملاحظات النشر." aria-describedby="field-rtl-arabic-notes-description"></textarea>
    <div class="field-description form-text" id="field-rtl-arabic-notes-description">تُظهر هذه الملاحظات فرق الدعم قبل الإقلاع.</div>
  </div>
</div>
מופיע בלוח הפריסה ובקישורי הצוות.
הערות אלה מוצגות לצוותי התמיכה לפני ההשקה.
<div class="w-100" dir="rtl">
  <div class="field">
    <label class="form-label" for="field-rtl-hebrew-project">שם הפרויקט</label>
    <input class="form-control" id="field-rtl-hebrew-project" type="text" placeholder="marketing-site" aria-describedby="field-rtl-hebrew-project-description">
    <div class="field-description form-text" id="field-rtl-hebrew-project-description">מופיע בלוח הפריסה ובקישורי הצוות.</div>
  </div>
  <div class="field">
    <label class="form-label" for="field-rtl-hebrew-notes">הערות פריסה</label>
    <textarea class="form-control" id="field-rtl-hebrew-notes" rows="3" placeholder="הוסף הערות פריסה." aria-describedby="field-rtl-hebrew-notes-description"></textarea>
    <div class="field-description form-text" id="field-rtl-hebrew-notes-description">הערות אלה מוצגות לצוותי התמיכה לפני ההשקה.</div>
  </div>
</div>
Displayed in the release dashboard and team links.
These notes show support teams before launch.
<div class="w-100" dir="ltr">
  <div class="field">
    <label class="form-label" for="field-rtl-english-project">Project name</label>
    <input class="form-control" id="field-rtl-english-project" type="text" placeholder="marketing-site" aria-describedby="field-rtl-english-project-description">
    <div class="field-description form-text" id="field-rtl-english-project-description">Displayed in the release dashboard and team links.</div>
  </div>
  <div class="field">
    <label class="form-label" for="field-rtl-english-notes">Deployment notes</label>
    <textarea class="form-control" id="field-rtl-english-notes" rows="3" placeholder="Add deployment notes." aria-describedby="field-rtl-english-notes-description"></textarea>
    <div class="field-description form-text" id="field-rtl-english-notes-description">These notes show support teams before launch.</div>
  </div>
</div>

Component reference

Status
Accepted
Runtime
native HTML/CSS
Markup
Moo UI documented extension
Reference

For Bootstrap's own form layout, validation states, and accessibility notes, see the Bootstrap Validation documentation.

Settings

Theme
Choose how Moo UI looks on this device.
Sidebar
Choose how the sidebar sits on the page.
Theme Builder
Tune catalog tokens and chart colors for this browser.
Base color
Theme color
Chart color
Heading font
Body font
Radius
Direction
Choose the reading direction. RTL flips the layout live.
Reset

Restore the default appearance.