Snippets Form Wizard

Bootstrap 5 Multi-Step Form Wizard with Progress Bar

A four-step checkout wizard with a segmented progress bar, validation on each step and a final order summary.

Bootstrap 5 No jQuery Jun 2020 5.8K views

<section class="wdw-stage">
  <div class="container" style="max-width: 640px">
    <form class="wdw-card p-4 p-md-5" id="wizard" novalidate>
      <div class="d-flex justify-content-between align-items-center mb-3">
        <span class="wdw-eyebrow" id="wizStep" aria-live="polite">Step 1 of 4</span>
        <span class="wdw-muted small" id="wizPct">25%</span>
      </div>
      <ol class="wiz-steps list-unstyled d-flex mb-4" id="wizBars" aria-hidden="true">
        <li class="is-current"><span class="wiz-dot">1</span><span class="wiz-lbl">Details</span></li>
        <li><span class="wiz-dot">2</span><span class="wiz-lbl">Delivery</span></li>
        <li><span class="wiz-dot">3</span><span class="wiz-lbl">Payment</span></li>
        <li><span class="wiz-dot">4</span><span class="wiz-lbl">Confirm</span></li>
      </ol>

      <fieldset class="wiz-pane">
        <legend class="wdw-heading h3 mb-1" tabindex="-1">Customer details</legend>
        <p class="wdw-muted mb-4">Tell us who is placing the order.</p>
        <div class="form-floating mb-3"><input type="text" class="form-control" id="wName" aria-describedby="wNameErr" placeholder="Name" required autocomplete="name"><label for="wName">Full name</label><div class="invalid-feedback" id="wNameErr">Enter your full name</div></div>
        <div class="form-floating mb-3"><input type="email" class="form-control" id="wEmail" aria-describedby="wEmailErr" placeholder="Email" required autocomplete="email"><label for="wEmail">Email</label><div class="invalid-feedback" id="wEmailErr">Enter a valid email, like [email protected]</div></div>
        <div class="form-floating mb-3"><input type="tel" class="form-control" id="wPhone" aria-describedby="wPhoneErr" placeholder="Phone" required autocomplete="tel"><label for="wPhone">Phone number</label><div class="invalid-feedback" id="wPhoneErr">Enter a phone number with 7 to 15 digits</div></div>
        <div class="form-floating"><input type="text" class="form-control" id="wAddr" aria-describedby="wAddrErr" placeholder="Address" required autocomplete="street-address"><label for="wAddr">Street address</label><div class="invalid-feedback" id="wAddrErr">Enter your street address</div></div>
      </fieldset>

      <fieldset class="wiz-pane" hidden>
        <legend class="wdw-heading h3 mb-1" tabindex="-1">Delivery</legend>
        <p class="wdw-muted mb-4">Choose how fast you want it.</p>
        <div class="d-grid gap-3">
          <input type="radio" class="btn-check" name="ship" id="s1" value="Standard" checked><label class="wiz-opt" for="s1"><span><strong>Standard</strong><small>3 to 5 business days</small></span><span class="fw-bold">Free</span></label>
          <input type="radio" class="btn-check" name="ship" id="s2" value="Express"><label class="wiz-opt" for="s2"><span><strong>Express</strong><small>1 to 2 business days</small></span><span class="fw-bold">$9</span></label>
          <input type="radio" class="btn-check" name="ship" id="s3" value="Same-day"><label class="wiz-opt" for="s3"><span><strong>Same day</strong><small>Order before noon</small></span><span class="fw-bold">$19</span></label>
        </div>
      </fieldset>

      <fieldset class="wiz-pane" hidden>
        <legend class="wdw-heading h3 mb-1" tabindex="-1">Payment</legend>
        <p class="wdw-muted mb-4">Demo only. Nothing is sent anywhere.</p>
        <div class="form-floating mb-3"><input type="text" class="form-control" id="wCard" aria-describedby="wCardErr" placeholder="Card" inputmode="numeric" required autocomplete="cc-number"><label for="wCard">Card number</label><div class="invalid-feedback" id="wCardErr">Enter a 13 to 19 digit card number</div></div>
        <div class="row g-3">
          <div class="col-6"><div class="form-floating"><input type="text" class="form-control" id="wExp" aria-describedby="wExpErr" placeholder="MM/YY" required autocomplete="cc-exp"><label for="wExp">Expiry (MM/YY)</label><div class="invalid-feedback" id="wExpErr">Use MM/YY with a future date</div></div></div>
          <div class="col-6"><div class="form-floating"><input type="text" class="form-control" id="wCvc" aria-describedby="wCvcErr" placeholder="CVC" inputmode="numeric" required autocomplete="cc-csc"><label for="wCvc">CVC</label><div class="invalid-feedback" id="wCvcErr">Enter the 3 or 4 digit code</div></div></div>
        </div>
      </fieldset>

      <fieldset class="wiz-pane" hidden>
        <legend class="wdw-heading h3 mb-1" tabindex="-1">Confirm order</legend>
        <p class="wdw-muted mb-4">Check everything looks right.</p>
        <dl class="row mb-0 g-2" id="wSummary"></dl>
        <div class="alert alert-success d-none mt-4 mb-0" id="wDone" role="status">Order confirmed. A receipt is on its way to your inbox.</div>
      </fieldset>

      <div class="wiz-total d-flex justify-content-between align-items-center mt-4 p-3 rounded-3 bg-body-tertiary">
        <span class="text-body-secondary small">Order total <span class="d-none d-sm-inline">(2 items)</span></span>
        <strong class="text-body-emphasis" id="wTotal">$48.00</strong>
      </div>
      <div class="d-flex justify-content-between gap-2 mt-3">
        <button type="button" class="btn btn-outline-secondary rounded-pill px-4 invisible" id="wBack">Back</button>
        <button type="button" class="btn btn-primary rounded-pill px-4" id="wNext">Next
          <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg></button>
      </div>
      <p class="wdw-muted small text-center mt-3 mb-0 d-flex justify-content-center align-items-center gap-2"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>Secure checkout. Free returns within 30 days.</p>
    </form>
  </div>
</section>

Built on Bootstrap 5.3.8 with plain JavaScript — no jQuery. Supports light and dark mode via data-bs-theme.

Free to use in personal and commercial projects under the MIT license.