Source Code

<div class="sw-card">
  <div class="sw-dots">
    <div class="sw-dot sw-active" id="swDot0"><span>1</span></div>
    <div class="sw-line"></div>
    <div class="sw-dot" id="swDot1"><span>2</span></div>
    <div class="sw-line"></div>
    <div class="sw-dot" id="swDot2"><span>3</span></div>
  </div>

  <form id="swForm" novalidate>
    <div class="sw-step sw-step-active" id="swStep0">
      <h2>Create your account</h2>
      <label class="sw-field">
        <span>Full name</span>
        <input type="text" id="swName" placeholder="Ava Thompson" autocomplete="name" />
      </label>
      <label class="sw-field">
        <span>Email address</span>
        <input type="text" id="swEmail" placeholder="ava@example.com" autocomplete="email" />
      </label>
      <p class="sw-error" id="swError0"></p>
    </div>

    <div class="sw-step" id="swStep1">
      <h2>Secure your account</h2>
      <label class="sw-field">
        <span>Password</span>
        <input type="password" id="swPassword" placeholder="At least 8 characters" autocomplete="new-password" />
      </label>
      <label class="sw-field">
        <span>Confirm password</span>
        <input type="password" id="swConfirm" placeholder="Re-enter your password" autocomplete="new-password" />
      </label>
      <p class="sw-error" id="swError1"></p>
    </div>

    <div class="sw-step" id="swStep2">
      <h2>Choose a plan</h2>
      <div class="sw-plans">
        <label class="sw-plan">
          <input type="radio" name="swPlan" value="free" checked />
          <span class="sw-plan-name">Free</span>
          <span class="sw-plan-price">$0/mo</span>
        </label>
        <label class="sw-plan">
          <input type="radio" name="swPlan" value="pro" />
          <span class="sw-plan-name">Pro</span>
          <span class="sw-plan-price">$12/mo</span>
        </label>
        <label class="sw-plan">
          <input type="radio" name="swPlan" value="team" />
          <span class="sw-plan-name">Team</span>
          <span class="sw-plan-price">$29/mo</span>
        </label>
      </div>
    </div>

    <div class="sw-step" id="swSuccess">
      <div class="sw-success-icon">
        <svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M5 13l4 4L19 7"/></svg>
      </div>
      <h2>Account created!</h2>
      <p>Welcome aboard — check your inbox to confirm your email address.</p>
    </div>

    <div class="sw-nav" id="swNav">
      <button type="button" class="sw-btn sw-btn-ghost" id="swBack">Back</button>
      <button type="button" class="sw-btn sw-btn-primary" id="swNext">Next</button>
    </div>
  </form>
</div>

Multi-Step Signup Wizard — Free HTML CSS JS Snippet

Multi-Step Signup Wizard · Forms · Plain HTML, CSS & JS · Live preview

What's included

Features

Three-step wizard (name/email, password, plan) with a step-dot progress indicator at the top
Blocking per-step validation with inline error messages that prevent advancing until fixed
Email validation checks for the presence of "@"; password validation checks length and confirmation match
Back/Next navigation that preserves already-entered field values across steps
Radio-card plan selection step styled with a highlighted border on the checked option
Dedicated success screen shown after the final "Create account" submission
Dot indicator distinguishes current, completed, and upcoming steps with distinct styling
Pure vanilla JS state machine driving step visibility, no routing or framework needed

About this UI Snippet

Multi-Step Signup Wizard — Validated 3-Step Account Creation Flow

Screenshot of the Multi-Step Signup Wizard snippet rendered live

Long signup forms convert better when broken into short, focused steps. This snippet implements a 3-step wizard — name/email, password, and plan selection — with a step-dot indicator at the top, per-step client-side validation that blocks advancement until satisfied, and a final success screen.

Step visibility and the dot indicator

Each step is a <div class="sw-step"> toggled visible via a .sw-step-active class; only the current index's step is ever shown. The dot row mirrors the same index: the current dot gets .sw-active, and every dot before it gets .sw-done, giving a clear sense of progress and completed steps at a glance.

Blocking, per-step validation

validateStep(index) runs only against the fields relevant to the current step. Step 1 requires a non-empty name and an email containing @; step 2 requires a password of at least 8 characters that matches its confirmation field. Clicking Next calls this function first and returns early — without advancing current — if validation fails, instead rendering an inline error message in that step's .sw-error element.

Plan selection and the success state

Step 3 is a set of radio-styled plan cards (Free/Pro/Team) with no required validation beyond a default selection. Submitting from the final step hides all wizard steps and the dot indicator, then reveals a dedicated success panel with a checkmark icon and confirmation copy — a clear terminal state distinct from any of the numbered steps.

Step by step

How to Use

  1. 1
    Load the snippetClick "Multi-Step Signup Wizard" in the sidebar to load its HTML, CSS, and JS into the editor panels. The preview updates instantly.
  2. 2
    Edit the codeModify any panel — HTML, CSS, or JS. The preview refreshes as you type. Use Reset in each panel header to restore the original.
  3. 3
    Preview on devicesClick the Mobile (375px), Tablet (768px), or Desktop buttons in the preview header to check responsiveness.
  4. 4
    Export in your formatClick "HTML" to download a standalone file, "JSX" for a React component, "Tailwind" for a React + Tailwind CSS component, "Tailwind HTML" for a standalone HTML file with Tailwind CDN, "Vue" for a Vue 3 SFC with <template>/<script setup>/<style scoped>, or "Angular" for a standalone Angular .component.ts file. "Copy all" copies the full code to clipboard.
  5. 5
    Save your versionClick "Save as", type a name, and press Enter. Your snippet saves to IndexedDB and appears in the Saved tab.

Real-world uses

Common Use Cases

SaaS account creation
Break a long signup form into digestible steps to reduce abandonment.
Subscription plan selection
Combine account creation with plan selection in a single guided flow.
Multi-step checkout or setup forms
The same step/dot/validation pattern applies to checkout, surveys, or setup wizards.
Teaching client-side form validation
A clear example of gating navigation on a small, explicit set of validation rules.

Got questions?

Frequently Asked Questions

The Next button click handler calls validateStep(current) first. If it returns false, the function returns immediately without incrementing the current step index, and an inline error message is shown in that step.

The check only requires the trimmed email string to be non-empty and contain an "@" character — a lightweight check appropriate for a demo, not full RFC email validation.

Yes — add another label.sw-plan block with a radio input sharing the swPlan name; the existing CSS automatically highlights whichever option is checked.

All wizard steps and the dot indicator are hidden, and a dedicated success panel with a checkmark icon and confirmation message is shown in their place.