Snippets Form

Bootstrap 5 Multi-Step Registration Form with Validation

A three-step registration flow with a progress indicator, floating-label fields with inline validation and a confirmation screen, beside a full-height photo panel.

Bootstrap 5 No jQuery Nov 2020 2.3K views

<section class="wdw-stage">
  <div class="container" style="max-width: 980px">
    <div class="wdw-card overflow-hidden">
      <div class="row g-0">
        <aside class="col-lg-5 wdw-aurora d-none d-lg-flex flex-column justify-content-between p-5">
          <span class="fw-bold fs-5">Northwind</span>
          <div>
            <span class="wdw-eyebrow text-white mb-2">Join the community</span>
            <h2 class="fw-bold mb-2" style="letter-spacing:-.02em">Three quick steps and you are in.</h2>
            <p class="mb-4 text-white">Set up your account, tell us who you are, then confirm and finish.</p>
            <ul class="list-unstyled d-flex flex-column gap-2 mb-0" id="rgChecklist" aria-label="Setup progress">
              <li class="wdw-check" data-for="0"><span class="wdw-tick" aria-hidden="true"></span>Create your login</li>
              <li class="wdw-check" data-for="1"><span class="wdw-tick" aria-hidden="true"></span>Add your details</li>
              <li class="wdw-check" data-for="2"><span class="wdw-tick" aria-hidden="true"></span>Account ready</li>
            </ul>
          </div>
        </aside>
        <div class="col-lg-7 p-4 p-md-5">
          <ol class="wdw-stepper list-unstyled d-flex align-items-center gap-2 mb-2" aria-label="Progress">
            <li class="wdw-step active" aria-current="step"><span class="wdw-dot" aria-hidden="true">1</span><span class="visually-hidden-sm"><span class="visually-hidden">Step 1: </span>Account</span></li>
            <li class="wdw-step"><span class="wdw-dot" aria-hidden="true">2</span><span class="visually-hidden-sm"><span class="visually-hidden">Step 2: </span>Profile</span></li>
            <li class="wdw-step"><span class="wdw-dot" aria-hidden="true">3</span><span class="visually-hidden-sm"><span class="visually-hidden">Step 3: </span>Done</span></li>
          </ol>
          <div class="progress mb-4" style="height:4px" role="progressbar" aria-label="Registration progress" aria-valuemin="0" aria-valuemax="100" aria-valuenow="33" id="rgProgress">
            <div class="progress-bar" style="width:33%"></div>
          </div>

          <form id="regForm" novalidate>
            <fieldset class="wdw-pane" data-pane="0">
              <legend class="wdw-heading h4 mb-1">Create your login</legend>
              <p class="wdw-muted mb-4">Choose a username and a strong password.</p>
              <div class="form-floating mb-3">
                <input type="text" class="form-control" id="rgUser" placeholder="Username" required pattern="[A-Za-z0-9]{3,20}" autocomplete="username">
                <label for="rgUser">Username</label>
                <div class="form-text">3 to 20 letters or numbers.</div>
                <div class="invalid-feedback">Use 3 to 20 letters or numbers only.</div>
              </div>
              <div class="form-floating mb-3">
                <input type="password" class="form-control" id="rgPass" placeholder="Password" required minlength="8" autocomplete="new-password">
                <label for="rgPass">Password</label>
                <div class="form-text">At least 8 characters.</div>
                <div class="invalid-feedback">Password needs at least 8 characters.</div>
              </div>
              <div class="form-floating mb-2">
                <input type="password" class="form-control" id="rgPass2" placeholder="Confirm password" required autocomplete="new-password">
                <label for="rgPass2">Confirm password</label>
                <div class="invalid-feedback">Passwords do not match.</div>
              </div>
              <div class="d-flex justify-content-between align-items-center mb-4 small">
                <span id="rgMatch" class="wdw-muted" aria-live="polite"></span>
                <div class="form-check form-switch mb-0"><input class="form-check-input" type="checkbox" role="switch" id="rgShow"><label class="form-check-label" for="rgShow">Show passwords</label></div>
              </div>
            </fieldset>

            <fieldset class="wdw-pane" data-pane="1" hidden>
              <legend class="wdw-heading h4 mb-1">Tell us about you</legend>
              <p class="wdw-muted mb-4">We use this to personalise your account.</p>
              <div class="row g-3 mb-3">
                <div class="col-sm-6"><div class="form-floating">
                  <input type="text" class="form-control" id="rgFirst" placeholder="First name" required pattern="[A-Za-z' -]+" autocomplete="given-name">
                  <label for="rgFirst">First name</label>
                  <div class="invalid-feedback">Letters only, please.</div>
                </div></div>
                <div class="col-sm-6"><div class="form-floating">
                  <input type="text" class="form-control" id="rgLast" placeholder="Last name" required pattern="[A-Za-z' -]+" autocomplete="family-name">
                  <label for="rgLast">Last name</label>
                  <div class="invalid-feedback">Letters only, please.</div>
                </div></div>
              </div>
              <div class="form-floating mb-4">
                <input type="email" class="form-control" id="rgEmail" placeholder="Email" required autocomplete="email">
                <label for="rgEmail">Email address</label>
                <div class="invalid-feedback">Type a valid email address.</div>
              </div>
            </fieldset>

            <div class="wdw-pane text-center py-4" data-pane="2" hidden>
              <span class="wdw-icon mb-3 text-success" style="width:4rem;height:4rem;background:var(--bs-success-bg-subtle);color:var(--bs-success)"><svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5 12 5 5 9-10"/></svg></span>
              <h2 class="wdw-heading h4 mb-1" tabindex="-1" id="rgDone">Welcome aboard, <span id="rgName">friend</span>!</h2>
              <p class="wdw-muted mb-4">Your account is ready. We sent a confirmation to <strong id="rgMail"></strong>.</p>
              <dl class="wdw-card-sm text-start p-3 mb-4 row g-2 mx-0 small">
                <dt class="col-4 wdw-muted fw-normal">Username</dt><dd class="col-8 mb-0 fw-semibold" id="rgSumUser"></dd>
                <dt class="col-4 wdw-muted fw-normal">Name</dt><dd class="col-8 mb-0 fw-semibold" id="rgSumName"></dd>
                <dt class="col-4 wdw-muted fw-normal">Email</dt><dd class="col-8 mb-0 fw-semibold text-break" id="rgSumMail"></dd>
              </dl>
              <a href="#" class="btn btn-primary rounded-pill px-4">Go to dashboard</a>
            </div>

            <div class="d-flex justify-content-between gap-2" id="rgNav">
              <button type="button" class="btn btn-outline-secondary rounded-pill px-4 invisible" id="rgBack">Back</button>
              <button type="submit" class="btn btn-primary rounded-pill px-4" id="rgNext">Next step</button>
            </div>
          </form>
        </div>
      </div>
    </div>
  </div>
</section>

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