Bootstrap 5 Multi-Step Form
A multi-step form breaks a long or complex form into sequential sections, showing one step at a time with progress indicators between them. Bootstrap 5 does not ship a dedicated multi-step form component, but you can build one using the tab system, nav pills, cards, and utility classes combined with minimal JavaScript to control step visibility. Use this pattern whenever a form has more than five fields, collects sensitive data across logical groups (contact details, then payment, then confirmation), or when research shows users abandon single-page forms at high rates.
Primary Class
.multi-step-formCommon Use Cases
- →SaaS onboarding flow that collects account details on step 1, billing information on step 2, and team member invitations on step 3
- →Insurance quote calculator that walks users through vehicle details, driver history, and coverage preferences before showing a price
- →Event registration form that separates ticket selection, attendee details, and dietary or accessibility requirements into distinct steps
- →Job application form that groups resume upload and work history on step 1, references on step 2, and equal opportunities data on step 3
Variants & Classes
| Variant | Description |
|---|---|
| Multi-Step Form Default | Standard multi-step form with Bootstrap's default styling. |
| Multi-Step Form Responsive | Responsive variant that adapts to different screen sizes. |
Code Example
<div class="container py-5">
<div class="row justify-content-center">
<div class="col-lg-7">
<!-- Step progress indicator -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div class="step-item text-center">
<div class="step-circle bg-primary text-white rounded-circle d-inline-flex align-items-center justify-content-center" style="width:40px;height:40px;" id="circle-1">1</div>
<div class="small mt-1 fw-semibold">Account</div>
</div>
<div class="flex-grow-1 border-top border-2 mx-2"></div>
<div class="step-item text-center">
<div class="step-circle bg-secondary text-white rounded-circle d-inline-flex align-items-center justify-content-center" style="width:40px;height:40px;" id="circle-2">2</div>
<div class="small mt-1 text-muted">Billing</div>
</div>
<div class="flex-grow-1 border-top border-2 mx-2"></div>
<div class="step-item text-center">
<div class="step-circle bg-secondary text-white rounded-circle d-inline-flex align-items-center justify-content-center" style="width:40px;height:40px;" id="circle-3">3</div>
<div class="small mt-1 text-muted">Confirm</div>
</div>
</div>
<div class="card shadow-sm border-0">
<div class="card-body p-4">
<!-- Step 1: Account Details -->
<div class="step-panel" id="step-1">
<h5 class="card-title mb-4">Create your account</h5>
<div class="mb-3">
<label for="fullName" class="form-label">Full name</label>
<input type="text" class="form-control" id="fullName" placeholder="Jane Smith">
</div>
<div class="mb-3">
<label for="email" class="form-label">Email address</label>
<input type="email" class="form-control" id="email" placeholder="jane@example.com">
</div>
<div class="mb-4">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" placeholder="Min. 8 characters">
</div>
<div class="d-flex justify-content-end">
<button class="btn btn-primary" onclick="goToStep(2)">Next: Billing <i class="bi bi-arrow-right ms-1"></i></button>
</div>
</div>
<!-- Step 2: Billing -->
<div class="step-panel d-none" id="step-2">
<h5 class="card-title mb-4">Billing information</h5>
<div class="mb-3">
<label for="cardName" class="form-label">Name on card</label>
<input type="text" class="form-control" id="cardName" placeholder="Jane Smith">
</div>
<div class="mb-3">
<label for="cardNumber" class="form-label">Card number</label>
<input type="text" class="form-control" id="cardNumber" placeholder="1234 5678 9012 3456">
</div>
<div class="row g-3 mb-4">
<div class="col-6">
<label for="expiry" class="form-label">Expiry date</label>
<input type="text" class="form-control" id="expiry" placeholder="MM / YY">
</div>
<div class="col-6">
<label for="cvv" class="form-label">CVV</label>
<input type="text" class="form-control" id="cvv" placeholder="123">
</div>
</div>
<div class="d-flex justify-content-between">
<button class="btn btn-outline-secondary" onclick="goToStep(1)"><i class="bi bi-arrow-left me-1"></i> Back</button>
<button class="btn btn-primary" onclick="goToStep(3)">Next: Confirm <i class="bi bi-arrow-right ms-1"></i></button>
</div>
</div>
<!-- Step 3: Confirm -->
<div class="step-panel d-none" id="step-3">
<h5 class="card-title mb-4">Review and confirm</h5>
<div class="alert alert-light border mb-4">
<p class="mb-1"><strong>Plan:</strong> Pro Monthly at $29/month</p>
<p class="mb-1"><strong>Billing:</strong> Card ending in 3456</p>
<p class="mb-0"><strong>Renews:</strong> Automatically each month. Cancel anytime.</p>
</div>
<div class="form-check mb-4">
<input class="form-check-input" type="checkbox" id="termsCheck">
<label class="form-check-label" for="termsCheck">
I agree to the <a href="#">Terms of Service</a> and <a href="#">Privacy Policy</a>
</label>
</div>
<div class="d-flex justify-content-between">
<button class="btn btn-outline-secondary" onclick="goToStep(2)"><i class="bi bi-arrow-left me-1"></i> Back</button>
<button class="btn btn-success" type="submit">Confirm and Subscribe</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
function goToStep(step) {
document.querySelectorAll('.step-panel').forEach(function(panel) {
panel.classList.add('d-none');
});
document.getElementById('step-' + step).classList.remove('d-none');
[1, 2, 3].forEach(function(n) {
var circle = document.getElementById('circle-' + n);
if (n < step) {
circle.classList.remove('bg-secondary');
circle.classList.add('bg-success');
} else if (n === step) {
circle.classList.remove('bg-secondary', 'bg-success');
circle.classList.add('bg-primary');
} else {
circle.classList.remove('bg-primary', 'bg-success');
circle.classList.add('bg-secondary');
}
});
}
</script>Live Examples
Basic Multi-Step Form
Canvas Framework Variants
The Canvas template extends Bootstrap 5 with 1,658+ component variants. Generate any of these using Canvas Builder:
- ✓Canvas Builder generated multi-step form with custom colours
- ✓Multi-Step Form with interactive states
- ✓Responsive multi-step form for all screen sizes
Best Practices
Validate each step before advancing
Run Bootstrap 5 native validation (using the `was-validated` class on the form and the `required` attribute on inputs) inside your `goToStep` function before showing the next panel, so users cannot skip required fields and encounter a wall of errors at the final step.
Preserve field values when navigating backwards
Because the panels use `d-none` instead of being removed from the DOM, field values persist automatically when users click Back, which avoids one of the most frustrating multi-step form experiences without any extra state management.
Mark completed steps visually
Swap the step circle colour to `bg-success` once a step is passed (as shown in the `goToStep` function above) so users can see their progress at a glance and feel confident they are moving forward through the form.
Keep each step under five fields
If any single step requires more than five fields, consider whether you can split it further or use a collapsible accordion within that step; cognitive overload per screen undermines the entire point of breaking the form apart.