Step indicators that visualize progress through a multi-step process \u2014 from simple numbered progress bars to full wizard interfaces with form validation and back/next navigation.
Basic Horizontal Stepper
A numbered step indicator showing completed, active, and upcoming steps connected by lines. Completed steps display a checkmark, the active step is highlighted with a glow effect, and upcoming steps remain dimmed.
A fully interactive wizard with back/next navigation. Each step displays different content, and the step indicator updates to reflect the current position. The final step changes the Next button to a green Finish button.
interactive-wizard
Live
untitled.html
HTML
1
<div class="wizard">
2
<div class="w-stepper">
3
<div class="ws done" data-step="0">
4
<span class="ws-n">
5
1
6
</span>
7
<span class="ws-t">
8
Details
9
</span>
10
</div>
11
<div class="ws-line done">
12
</div>
13
<div class="ws active" data-step="1">
14
<span class="ws-n">
15
2
16
</span>
17
<span class="ws-t">
18
Preferences
19
</span>
20
</div>
21
<div class="ws-line">
22
</div>
23
<div class="ws" data-step="2">
24
<span class="ws-n">
25
3
26
</span>
27
<span class="ws-t">
28
Review
29
</span>
30
</div>
31
</div>
32
<div class="w-content" id="w-content">
33
<div class="w-panel active" data-panel="0">
34
<h4>
35
Account Details
36
</h4>
37
<p>
38
Enter your name and email address to create your account.
let step=1;const total=3;const steps=document.querySelectorAll('.ws');const lines=document.querySelectorAll('.ws-line');const panels=document.querySelectorAll('.w-panel');const back=document.getElementById('w-back');const next=document.getElementById('w-next');function update(){steps.forEach((s,i)=>{s.classList.remove('done','active');if(i<step)s.classList.add('done');if(i===step)s.classList.add('active')});lines.forEach((l,i)=>l.classList.toggle('done',i<step));panels.forEach((p,i)=>{p.classList.toggle('active',i===step)});back.disabled=step===0;next.textContent=step===total-1?'Finish':'Next';next.style.background=step===total-1?'#22C55E':''}back.addEventListener('click',()=>{if(step>0){step--;update()}});next.addEventListener('click',()=>{if(step<total-1){step++;update()}else{next.textContent='Done!';next.style.background='#22C55E'}})
preview
Vertical Stepper
A vertical step layout for sidebars, mobile views, or contexts where horizontal space is limited. Each step shows its content inline below the indicator, connected by a vertical line.
Items are being picked and packed at the warehouse.
40
</p>
41
<span class="vs-time">
42
15 minutes ago
43
</span>
44
</div>
45
</div>
46
<div class="vs active">
47
<div class="vs-indicator">
48
<div class="vs-dot">
49
</div>
50
<div class="vs-line">
51
</div>
52
</div>
53
<div class="vs-body">
54
<h5>
55
Shipped
56
</h5>
57
<p>
58
Your package is on its way via FedEx Express.
59
</p>
60
<span class="vs-time">
61
In transit
62
</span>
63
</div>
64
</div>
65
<div class="vs">
66
<div class="vs-indicator">
67
<div class="vs-dot">
68
</div>
69
</div>
70
<div class="vs-body">
71
<h5>
72
Delivered
73
</h5>
74
<p>
75
Estimated arrival: tomorrow by 6 PM.
76
</p>
77
<span class="vs-time">
78
Pending
79
</span>
80
</div>
81
</div>
82
</div>
untitled.css
CSS
1
.v-stepper {
2
max-width:340px;
3
margin:16px auto;
4
padding:16px;
5
font-family:system-ui,
6
sans-serif
7
}
8
.vs {
9
display:flex;
10
gap:12px
11
}
12
.vs-indicator {
13
display:flex;
14
flex-direction:column;
15
align-items:center;
16
flex-shrink:0
17
}
18
.vs-dot {
19
width:24px;
20
height:24px;
21
border-radius:50%;
22
display:flex;
23
align-items:center;
24
justify-content:center;
25
border:2px solid #333;
26
background:#0A0A0A;
27
flex-shrink:0;
28
transition:all .3s
29
}
30
.vs.done .vs-dot {
31
background:#00FF41;
32
border-color:#00FF41;
33
color:#0A0A0A
34
}
35
.vs.active .vs-dot {
36
border-color:#00FF41;
37
color:#00FF41;
38
box-shadow:0 0 10px rgba(0,
39
255,
40
65,
41
.3)
42
}
43
.vs-line {
44
width:2px;
45
flex:1;
46
background:#222;
47
margin:4px 0
48
}
49
.vs.done .vs-line {
50
background:#00FF41
51
}
52
.vs-body {
53
padding-bottom:20px;
54
flex:1
55
}
56
.vs-body h5 {
57
font-size:12px;
58
font-weight:600;
59
color:#E0E0E0;
60
margin:0 0 4px
61
}
62
.vs.done .vs-body h5 {
63
color:#808080
64
}
65
.vs-body p {
66
font-size:11px;
67
color:#666;
68
margin:0 0 4px;
69
line-height:1.5
70
}
71
.vs-time {
72
font-size:10px;
73
color:#555
74
}
75
.vs.active .vs-time {
76
color:#00FF41
77
}
preview
Labeled Steps with Icons
Steps with icons, labels, and sub-labels for richer context. Useful for checkout flows and onboarding where each step has a clear title and description. Uses square icons instead of circles for visual variety.
A compact step indicator using a progress bar with step markers \u2014 minimal and space-efficient for toolbars and inline contexts. Shows current step, total steps, and percentage complete.
minimal-progress
Live
untitled.html
HTML
1
<div class="mini-progress">
2
<div class="mp-header">
3
<span class="mp-title">
4
Step 2 of 5
5
</span>
6
<span class="mp-pct">
7
40%
8
</span>
9
</div>
10
<div class="mp-track">
11
<div class="mp-fill" style="width:40%">
12
<div class="mp-dot">
13
</div>
14
</div>
15
<div class="mp-markers">
16
<span class="mp-m done">
17
</span>
18
<span class="mp-m done">
19
</span>
20
<span class="mp-m active">
21
</span>
22
<span class="mp-m">
23
</span>
24
<span class="mp-m">
25
</span>
26
</div>
27
</div>
28
</div>
untitled.css
CSS
1
.mini-progress {
2
max-width:340px;
3
margin:16px auto;
4
padding:16px 20px;
5
background:#111;
6
border:1px solid #222;
7
border-radius:8px;
8
font-family:system-ui,
9
sans-serif
10
}
11
.mp-header {
12
display:flex;
13
justify-content:space-between;
14
margin-bottom:10px
15
}
16
.mp-title {
17
font-size:11px;
18
color:#808080;
19
font-weight:500
20
}
21
.mp-pct {
22
font-size:11px;
23
color:#00FF41;
24
font-weight:700;
25
font-variant-numeric:tabular-nums
26
}
27
.mp-track {
28
position:relative;
29
height:4px;
30
background:#1A1A2E;
31
border-radius:2px
32
}
33
.mp-fill {
34
position:absolute;
35
top:0;
36
left:0;
37
height:100%;
38
background:linear-gradient(90deg,
39
#00FF41,
40
#00CC33);
41
border-radius:2px;
42
transition:width .4s ease;
43
display:flex;
44
align-items:center;
45
justify-content:flex-end
46
}
47
.mp-dot {
48
width:10px;
49
height:10px;
50
border-radius:50%;
51
background:#00FF41;
52
border:2px solid #0A0A0A;
53
box-shadow:0 0 6px rgba(0,
54
255,
55
65,
56
.4);
57
position:relative;
58
right:-5px
59
}
60
.mp-markers {
61
position:absolute;
62
top:50%;
63
left:0;
64
right:0;
65
display:flex;
66
justify-content:space-between;
67
transform:translateY(-50%);
68
padding:0 2px
69
}
70
.mp-m {
71
width:6px;
72
height:6px;
73
border-radius:50%;
74
background:#333;
75
border:1.5px solid #0A0A0A;
76
z-index:1
77
}
78
.mp-m.done {
79
background:#00FF41
80
}
81
.mp-m.active {
82
background:#00FF41;
83
box-shadow:0 0 6px rgba(0,
84
255,
85
65,
86
.4)
87
}
preview
Numbered Circles
A simple numbered circle indicator with connecting lines, designed for compact inline use. Each number is always visible (no checkmarks), making it clear which step the user is on. The connecting lines transition color as steps complete.
numbered-circles
Live
untitled.html
HTML
1
<div class="nc-demo">
2
<div class="nc-step done">
3
<span>
4
1
5
</span>
6
</div>
7
<div class="nc-line done">
8
</div>
9
<div class="nc-step done">
10
<span>
11
2
12
</span>
13
</div>
14
<div class="nc-line done">
15
</div>
16
<div class="nc-step active">
17
<span>
18
3
19
</span>
20
</div>
21
<div class="nc-line">
22
</div>
23
<div class="nc-step">
24
<span>
25
4
26
</span>
27
</div>
28
<div class="nc-line">
29
</div>
30
<div class="nc-step">
31
<span>
32
5
33
</span>
34
</div>
35
</div>
untitled.css
CSS
1
.nc-demo {
2
display:flex;
3
align-items:center;
4
justify-content:center;
5
gap:0;
6
padding:32px;
7
font-family:system-ui,
8
sans-serif
9
}
10
.nc-step {
11
width:28px;
12
height:28px;
13
border-radius:50%;
14
display:flex;
15
align-items:center;
16
justify-content:center;
17
font-size:11px;
18
font-weight:700;
19
border:2px solid #333;
20
color:#555;
21
background:#0A0A0A;
22
transition:all .3s;
23
flex-shrink:0
24
}
25
.nc-step.done {
26
background:#00FF41;
27
border-color:#00FF41;
28
color:#0A0A0A
29
}
30
.nc-step.active {
31
border-color:#00FF41;
32
color:#00FF41;
33
box-shadow:0 0 10px rgba(0,
34
255,
35
65,
36
.3)
37
}
38
.nc-line {
39
flex:1;
40
height:2px;
41
background:#222;
42
min-width:20px;
43
max-width:40px;
44
margin:0 -2px;
45
margin-bottom:14px
46
}
47
.nc-line.done {
48
background:#00FF41
49
}
preview
Error & Warning States
Steps can display error or warning states to indicate validation failures. An error state uses red styling to draw attention, while the step remains clickable for the user to go back and fix the issue.
Stepper transitions use CSS transitions on background-color, border-color, and box-shadow. The key is to transition the .done class toggling, which triggers smooth color changes on both the circle and connecting line.
stepper-transitions.css
CSS
1
/* Base step circle */
2
.step-circle {
3
width: 32px;
4
height: 32px;
5
border-radius: 50%;
6
border: 2px solid #333;
7
background: #0A0A0A;
8
color: #555;
9
transition: all 0.3s ease;
10
}
11
12
/* Completed state */
13
.step.done .step-circle {
14
background: #00FF41;
15
border-color: #00FF41;
16
color: #0A0A0A;
17
}
18
19
/* Active state with glow */
20
.step.active .step-circle {
21
border-color: #00FF41;
22
color: #00FF41;
23
box-shadow: 0 0 12px rgba(0, 255, 65, 0.3);
24
}
25
26
/* Connecting line */
27
.step-line {
28
height: 2px;
29
background: #222;
30
transition: background 0.3s ease;
31
}
32
33
.step-line.done {
34
background: #00FF41;
35
}
HTML Structure
A stepper uses an ordered list of step items, each containing an indicator (circle with number/check), label, and optional content. Connect adjacent steps with a line element and use aria-current="step" on the active step.
Use aria-current="step" on the active step element so screen readers announce the current position. Mark completed steps with aria-current="false".
⚠
warning
Avoid step labels longer than two words. Long labels break the visual rhythm and create layout shifts on smaller screens. Use tooltips for additional context.
✓
best practice
Allow users to click on completed steps to go back and edit previous entries. Never trap users in a wizard \u2014 back navigation should always be available.
Keep total step count under 7 \u2014 Miller's Law. For longer processes, group related steps into phases or sub-wizards.
Show estimated time remaining alongside step count for long wizards (e.g., "Step 2 of 5 \u00b7 ~3 min left").
Validate each step before allowing progression. Highlight errors inline rather than blocking the entire step.
Use the prefers-reduced-motion query to disable step transition animations for sensitive users.
On mobile, convert horizontal steppers to vertical \u2014 horizontal layouts with 4+ steps overflow on small screens.