Form Layout
Individual controls are only half the story — a form also needs consistent spacing between fields and a sensible arrangement of labels next to inputs. Bootstrap 4 gives you three layout tools for this: .form-group for standard stacked spacing, the grid combined with .col-form-label for horizontal (label-beside-input) forms, and .form-inline for compact single-line forms. We'll use these to lay out the full TrailMap "Submit a Trail" form.
.mb-3 directly to whatever wraps a label+input pair. If you're maintaining a Bootstrap 4
codebase, every .form-group you see needs to become a spacing decision (usually
.mb-3) when it's eventually migrated.Standard Spacing: .form-group
Wrap each label+input pair in a .form-group <div> to get consistent bottom margin between fields, without having to think about spacing on a field-by-field basis.
<div class="form-group">
<label for="trailName">Trail name</label>
<input type="text" class="form-control" id="trailName">
</div>
<div class="form-group">
<label for="trailDescription">Description</label>
<textarea class="form-control" id="trailDescription" rows="3"></textarea>
</div>
Horizontal Forms: Grid + .col-form-label
For a label-beside-input layout, wrap the pair in .form-group.row and split it into grid columns — a small column for the label using .col-form-label (which vertically centers the label text against the input's height), and a larger column for the control.
<div class="form-group row">
<label for="trailDistance" class="col-sm-3 col-form-label">Distance (km)</label>
<div class="col-sm-9">
<input type="number" class="form-control" id="trailDistance" step="0.1" min="0">
</div>
</div>
Inline Forms: .form-inline
Add .form-inline to the <form> element to lay all its controls out on a single line (flex row) instead of stacking them — useful for compact forms like a quick trail search bar, but too cramped for a full multi-field submission form.
<form class="form-inline">
<label class="mr-2" for="quickSearch">Search</label>
<input type="text" class="form-control mr-2" id="quickSearch" placeholder="Trail name...">
<button type="submit" class="btn btn-primary">Search</button>
</form>
Worked Example: Full TrailMap "Submit a Trail" Form
Putting the pieces together — every field wrapped in .form-group, with a horizontal row for distance so it sits neatly beside the difficulty select.
<!-- TrailMap: Submit a Trail — full layout with .form-group -->
<form>
<div class="form-group">
<label for="trailName">Trail name</label>
<input type="text" class="form-control" id="trailName" name="trail_name">
</div>
<div class="form-group">
<label for="trailDescription">Description</label>
<textarea class="form-control" id="trailDescription" name="description" rows="4"></textarea>
</div>
<div class="form-group row">
<label for="trailDifficulty" class="col-sm-3 col-form-label">Difficulty</label>
<div class="col-sm-9">
<select class="custom-select" id="trailDifficulty" name="difficulty">
<option value="easy">Easy</option>
<option value="moderate">Moderate</option>
<option value="hard">Hard</option>
</select>
</div>
</div>
<div class="form-group row">
<label for="trailDistance" class="col-sm-3 col-form-label">Distance (km)</label>
<div class="col-sm-9">
<input type="number" class="form-control" id="trailDistance" name="distance" step="0.1" min="0">
</div>
</div>
<div class="form-group">
<label for="trailRegion">Region</label>
<select class="form-control" id="trailRegion" name="region">
<option>Pacific Northwest</option>
<option>Rocky Mountains</option>
<option>Appalachian</option>
</select>
</div>
<div class="form-group">
<label for="trailPhoto">Trail photo</label>
<div class="custom-file">
<input type="file" class="custom-file-input" id="trailPhoto" name="photo" accept="image/*">
<label class="custom-file-label" for="trailPhoto">Choose a photo...</label>
</div>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" id="agreeTerms" name="agree_terms" required>
<label class="form-check-label" for="agreeTerms">I agree to TrailMap's submission terms</label>
</div>
<button type="submit" class="btn btn-primary">Submit Trail</button>
</form>
.was-validated class.