Progress Stepper — Free HTML CSS JS Wizard Snippet

Progress Stepper · Navigation · Plain HTML, CSS & JS · Live preview

Share & Support

What's included

Features

Three step states: done (checkmark, filled), active (number, accent ring), pending (grey)
.done class on .line fills the connector between completed steps
nextStep() and prevStep() manage state transitions via classList manipulation
querySelectorAll-based navigation — works with any number of steps
Guards: returns early at first/last step to prevent out-of-bounds navigation
box-shadow glow ring on .active dot — draws attention to current step
SVG checkmark icon on .done dots — no font icon library needed
Export as HTML file, React JSX, or React + Tailwind CSS
Mobile (375px), Tablet (768px), Desktop device preview buttons
Live split-pane editor — preview updates as you type

About this UI Snippet

Progress Stepper — Step States, Connecting Lines & Forward/Back Navigation

Screenshot of the Progress Stepper snippet rendered live

A progress stepper shows users where they are in a multi-step process — a checkout flow, an onboarding wizard, a form with multiple sections, or a setup guide. It communicates position ("you are on step 2 of 4"), history ("steps 1 is complete"), and future ("steps 3 and 4 remain"). This snippet implements a full stepper with three visual states, connecting line fill animation, and forward/back navigation.

The three step states

Each .step element carries one of three state classes at any time:

.done — completed step: the dot shows a checkmark SVG icon, the background fills with accent colour, and the connecting line after it fills. Steps can be navigated back to from done state.

.active — current step: the dot shows the step number, the border and text use the accent colour, and it has a glow ring via box-shadow.

Pending (no class) — future step: grey border, grey number, dimmed label.

The connecting lines

A .line div sits between each pair of steps. In the default state it is grey. When a step moves from .active to .done, the line after it gains the .done class: background: #6366f1. This fills the connector, visually showing that the path between steps has been traversed.

The JavaScript navigation

nextStep() finds the current active index, removes .active from it and adds .done, adds .done to the line between the current and next step, then adds .active to the next step. prevStep() reverses this: removes .active from current, removes .done from the preceding line, removes .done from the preceding step and adds .active back to it. Back and forward buttons are disabled at the ends via if (i >= steps.length - 1) return and if (i <= 0) return.

Adding more steps

To add a fourth step, add a new .step div and a new .line div before it in the HTML. The JavaScript uses querySelectorAll so it picks up any number of steps and lines automatically.

Connecting to form panels

In a real multi-step form, call nextStep() when the user clicks a Next button on each form panel. Before calling it, validate the current panel's fields. If validation fails, do not advance — show the errors instead.

Build with AI

Build, Understand, Optimize, and Extend It With AI

You don't have to trace the class-toggling logic by hand. Paste this snippet's HTML, CSS, and JS into an AI coding assistant like Claude and ask it to explain exactly how activeIndex uses findIndex against the done/active classes to locate the current step, and why nextStep and prevStep have to touch three elements (the outgoing step, the line, and the incoming step) in a specific order to stay consistent. The same assistant can help optimize it — for instance whether re-querying getSteps and getLines with querySelectorAll on every call is wasteful for a stepper with many steps, or whether the state should be tracked as a single index instead of derived from DOM classes each time. It's also useful for extending the effect: ask it to add per-step validation before advancing, a clickable step to jump directly to a completed step, or a vertical layout variant. Treat the code less like a finished artifact and more like a starting point for a conversation.

Prompt to recreate it

Copy this into your AI assistant of choice to build the effect from scratch, or as a jumping-off point for your own variant:

text
Build a multi-step "progress stepper" in plain HTML, CSS, and JavaScript using only classList toggling — no framework, no state library.

Requirements:
- A horizontal row of step elements, each containing a numbered dot and a label, separated by connector line elements between each pair of steps.
- Each step must support exactly three mutually exclusive visual states driven by CSS classes only: a done state (filled accent background, checkmark icon instead of the number, accent-colored label), an active state (accent-colored border with a soft box-shadow glow ring around the dot, dark label), and a default pending state (grey border, grey number, dimmed label).
- Connector lines must independently track a done state that fills them with the accent color once the step before them is completed.
- Write a nextStep function that locates the currently active step via findIndex against the active class, removes active and adds done to it, adds done to the connecting line immediately after it, then adds active to the following step. Write a prevStep function that reverses all three of those changes in the correct order.
- Both functions must guard against moving past the first or last step (do nothing if already at an end) rather than throwing or wrapping around.
- Use querySelectorAll so the logic works for any number of steps and lines without hardcoding indices or a fixed step count.
- Wire a Back and a Continue button to prevStep and nextStep respectively.

Step by step

How to Use

  1. 1
    Click Next and Back in the previewClick Next to advance through the steps. The dot fills, the line fills, and the next step activates. Click Back to reverse.
  2. 2
    Update the step labelsIn the HTML panel, change each .label span text to your actual step names — "Account", "Payment", "Confirm", etc.
  3. 3
    Set the initial active stepBy default step 1 starts as .active. Add the .done class to any preceding steps to start mid-flow.
  4. 4
    Add more stepsAdd a .line div and a .step div for each additional step. The JS uses querySelectorAll so it picks them up automatically.
  5. 5
    Change the accent colourFind #6366f1 in the CSS and replace with your brand colour. Updates the done/active dot fill, line fill, and glow ring.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component, or "Tailwind" for a React + Tailwind version.

Real-world uses

Common Use Cases

Multi-step checkout flows
Guide users through Cart, Shipping, Payment, and Confirm steps. Call nextStep() after validating each form section before advancing.
Onboarding wizards
Break a complex setup into discrete steps — account creation, team invite, configuration, and launch. The stepper shows progress and reduces overwhelm.
Multi-section forms
Split long forms into 3-4 manageable sections. Validate each section before allowing the user to advance. Use Back to let users correct previous sections.
Learn classList multi-state management
The stepper uses three mutually exclusive classes on each step. Edit the nextStep() and prevStep() functions to understand how state transitions are managed without frameworks.
Installation and setup guides
Use the stepper to guide users through a technical setup: Install, Configure, Connect, Launch. Mark steps done as the user completes each action.
Vertical stepper variant
Change .stepper to flex-direction: column and .line to a vertical bar (width: 2px; height: 32px) for a vertical timeline-style stepper. Useful for narrow layouts or mobile.

Got questions?

Frequently Asked Questions

nextStep() finds the active step index with findIndex, removes .active from it and adds .done, adds .done to the connecting line at that index, then adds .active to the next step. prevStep() reverses this: removes .active from current, removes .done from the preceding line, removes .done from the preceding step and restores .active to it.

In the HTML panel, add a <div class="line"></div> after the last step, then add a new <div class="step"><div class="dot">4</div><span class="label">Your Step</span></div>. The querySelectorAll selectors pick up any number of .step and .line elements automatically.

Add multiple form panel divs (one per step). Show only the active panel. In nextStep(), validate the current panel before advancing. If validation fails, call e.preventDefault() and show error messages instead of calling nextStep().

In the HTML, add class="done" to step 1 and class="done" to the line after it. Add class="active" to step 2 (instead of step 1). Remove .active from step 1.

Change .stepper to display: flex; flex-direction: column; align-items: flex-start. Change .line to width: 2px; height: 32px and remove its flex-shrink. Change .step to flex-direction: row so the dot and label sit side by side.

Yes. Click "JSX" to download a React component. In React, manage a currentStep number with useState. Derive the state of each step from the index relative to currentStep: index < currentStep is done, index === currentStep is active, index > currentStep is pending.