Floating Labels and Form Layout

Intermediate
11 min

Floating Labels and Form Layout

A form is more than a stack of inputs. Bootstrap offers floating labels for compact, modern-looking fields, and a set of conventions built on the grid for horizontal, inline and multi-column layouts. After this lesson you will be able to lay out a two-column signup form, a horizontal settings form with right-aligned labels, and a single-line search bar, each responsive by default.

Floating Labels

A floating label sits inside the input like a placeholder and slides up when the field has focus or a value. The markup order matters: the <input> comes before the <label>, and a placeholder attribute is required even though it is not displayed:

html
<div class="form-floating mb-3"> <input type="text" class="form-control" id="company" placeholder="Company"> <label for="company">Company</label> </div>

The CSS uses :placeholder-shown to know whether the field is empty, which is why the placeholder cannot be omitted.

Floating labels also work with .form-select and textareas:

html
<div class="form-floating mb-3"> <select class="form-select" id="tz" aria-label="Time zone"> <option selected>Asia/Kolkata</option> <option>Europe/London</option> </select> <label for="tz">Time zone</label> </div> <div class="form-floating"> <textarea class="form-control" id="notes" placeholder="Notes" style="height: 100px"></textarea> <label for="notes">Notes</label> </div>

Set an explicit height on textareas, otherwise they collapse to a single line. Floating labels do not support form-control-sm or -lg, and they can sit inside an .input-group only when the group has no validation feedback text.

Form Grid: Multi-Column Forms

Use the regular grid with g-* gutters. g-3 is the conventional spacing for form rows:

html
<form class="row g-3"> <div class="col-md-6"> <label for="first" class="form-label">First name</label> <input class="form-control" id="first"> </div> <div class="col-md-6"> <label for="last" class="form-label">Last name</label> <input class="form-control" id="last"> </div> <div class="col-md-8"> <label for="street" class="form-label">Street</label> <input class="form-control" id="street"> </div> <div class="col-md-4"> <label for="zip" class="form-label">ZIP</label> <input class="form-control" id="zip"> </div> </form>

Because the gutter is vertical as well as horizontal, you do not need mb-3 on every field. For very compact forms use g-2.

Horizontal Forms

A horizontal form places the label and control side by side. Each field is a .row, the label gets .col-form-label (which adds padding to align its text with the input text) and a column width:

html
<form> <div class="row mb-3"> <label for="hEmail" class="col-sm-3 col-form-label">Email</label> <div class="col-sm-9"> <input type="email" class="form-control" id="hEmail"> </div> </div> <div class="row mb-3"> <div class="col-sm-3">Notifications</div> <div class="col-sm-9"> <div class="form-check"> <input class="form-check-input" type="checkbox" id="hNotify"> <label class="form-check-label" for="hNotify">Send weekly digest</label> </div> </div> </div> <div class="row"> <div class="col-sm-9 offset-sm-3"> <button class="btn btn-primary">Save</button> </div> </div> </form>

Below sm the labels stack above the inputs automatically. Match col-form-label-sm / -lg with form-control-sm / -lg when sizing.

Inline Forms

Bootstrap 5 removed the .form-inline class. Build inline forms with the grid or flex utilities plus align-items-center and .visually-hidden labels:

html
<form class="row row-cols-lg-auto g-3 align-items-center"> <div class="col-12"> <label class="visually-hidden" for="q">Search</label> <input class="form-control" id="q" placeholder="Search"> </div> <div class="col-12"> <label class="visually-hidden" for="cat">Category</label> <select class="form-select" id="cat"> <option selected>All</option> <option>Docs</option> </select> </div> <div class="col-12"> <button class="btn btn-primary">Go</button> </div> </form>

row-cols-lg-auto makes each column content-sized from lg up; below that the fields stack full width.

Column Sizing and Auto Width

col-auto fits a column to its content, which is handy for a short field like a quantity next to a full-width one:

html
<div class="row g-2"> <div class="col-auto"><input class="form-control" style="width: 6rem" value="1"></div> <div class="col"><input class="form-control" placeholder="Item name"></div> </div>

Tips

  • Group related fields with <fieldset> and <legend>; Bootstrap resets their default styling.
  • Put the primary action at the end of the form and give it type="submit" so Enter submits.
  • Keep label text short with floating labels; long labels are truncated.
  • A <form> with .vstack.gap-3 is a clean alternative to mb-3 on every field for single-column forms.
Quick Quiz
Question 1 of 3

Why does a floating-label input need a `placeholder` attribute?

Key Takeaways

  • .form-floating wraps an input followed by its label; the input must have a placeholder.
  • Multi-column forms use row g-3 with col-* per field; the gutter supplies vertical spacing.
  • Horizontal forms use one .row per field with col-form-label on the label column.
  • Inline forms are built with row-cols-lg-auto and align-items-center, with labels kept accessible via .visually-hidden.
  • col-auto fits a column to its content for short fields.

Next lesson: Form Validation - show valid and invalid states with HTML5 constraints, custom feedback messages and server-side classes.

Floating Labels and Form Layout - Bootstrap | CodeYourCraft | CodeYourCraft