Step Indicator
processUSWDS-derived
A multi-step progress indicator showing completed, current, and remaining steps.
Reference: USWDS documentation ↗
Variants
Centered
- Personal information
- Household status
- Supporting documents
Step 2 of 3Household status
<div class="flex-step-indicator" data-variant="centered" aria-label="Progress">
<ol class="flex-step-indicator__segments">
<li class="flex-step-indicator__segment" data-state="complete"><span class="flex-step-indicator__segment-label">Personal information</span></li>
<li class="flex-step-indicator__segment" data-state="current" aria-current="step"><span class="flex-step-indicator__segment-label">Household status</span></li>
<li class="flex-step-indicator__segment"><span class="flex-step-indicator__segment-label">Supporting documents</span></li>
</ol>
<div class="flex-step-indicator__header">
<h4 class="flex-step-indicator__heading"><span class="flex-step-indicator__current-step">Step 2 of 3</span><span class="flex-step-indicator__heading-text">Household status</span></h4>
</div>
</div>Counters
- Personal information
- Household status
- Supporting documents
- Signature
- Review and submit
Step 3 of 5Supporting documents
<div class="flex-step-indicator" data-variant="counters" aria-label="Progress">
<ol class="flex-step-indicator__segments">
<li class="flex-step-indicator__segment" data-state="complete"><span class="flex-step-indicator__segment-label">Personal information</span></li>
<li class="flex-step-indicator__segment" data-state="complete"><span class="flex-step-indicator__segment-label">Household status</span></li>
<li class="flex-step-indicator__segment" data-state="current" aria-current="step"><span class="flex-step-indicator__segment-label">Supporting documents</span></li>
<li class="flex-step-indicator__segment"><span class="flex-step-indicator__segment-label">Signature</span></li>
<li class="flex-step-indicator__segment"><span class="flex-step-indicator__segment-label">Review and submit</span></li>
</ol>
<div class="flex-step-indicator__header">
<h4 class="flex-step-indicator__heading"><span class="flex-step-indicator__current-step">Step 3 of 5</span><span class="flex-step-indicator__heading-text">Supporting documents</span></h4>
</div>
</div>Default
- Personal information
- Household status
- Supporting documents
Step 2 of 3Household status
<div class="flex-step-indicator" aria-label="Progress">
<ol class="flex-step-indicator__segments">
<li class="flex-step-indicator__segment" data-state="complete"><span class="flex-step-indicator__segment-label">Personal information</span></li>
<li class="flex-step-indicator__segment" data-state="current" aria-current="step"><span class="flex-step-indicator__segment-label">Household status</span></li>
<li class="flex-step-indicator__segment"><span class="flex-step-indicator__segment-label">Supporting documents</span></li>
</ol>
<div class="flex-step-indicator__header">
<h4 class="flex-step-indicator__heading"><span class="flex-step-indicator__current-step">Step 2 of 3</span><span class="flex-step-indicator__heading-text">Household status</span></h4>
</div>
</div>No Labels
- Personal information
- Household status
- Supporting documents
Step 2 of 3Household status
<div class="flex-step-indicator" data-variant="no-labels" aria-label="Progress">
<ol class="flex-step-indicator__segments">
<li class="flex-step-indicator__segment" data-state="complete"><span class="flex-step-indicator__segment-label">Personal information</span></li>
<li class="flex-step-indicator__segment" data-state="current" aria-current="step"><span class="flex-step-indicator__segment-label">Household status</span></li>
<li class="flex-step-indicator__segment"><span class="flex-step-indicator__segment-label">Supporting documents</span></li>
</ol>
<div class="flex-step-indicator__header">
<h4 class="flex-step-indicator__heading"><span class="flex-step-indicator__current-step">Step 2 of 3</span><span class="flex-step-indicator__heading-text">Household status</span></h4>
</div>
</div>Small Counters
- Personal information
- Household status
- Supporting documents
- Signature
- Review and submit
Step 3 of 5Supporting documents
<div class="flex-step-indicator" data-variant="small-counters" aria-label="Progress">
<ol class="flex-step-indicator__segments">
<li class="flex-step-indicator__segment" data-state="complete"><span class="flex-step-indicator__segment-label">Personal information</span></li>
<li class="flex-step-indicator__segment" data-state="complete"><span class="flex-step-indicator__segment-label">Household status</span></li>
<li class="flex-step-indicator__segment" data-state="current" aria-current="step"><span class="flex-step-indicator__segment-label">Supporting documents</span></li>
<li class="flex-step-indicator__segment"><span class="flex-step-indicator__segment-label">Signature</span></li>
<li class="flex-step-indicator__segment"><span class="flex-step-indicator__segment-label">Review and submit</span></li>
</ol>
<div class="flex-step-indicator__header">
<h4 class="flex-step-indicator__heading"><span class="flex-step-indicator__current-step">Step 3 of 5</span><span class="flex-step-indicator__heading-text">Supporting documents</span></h4>
</div>
</div>Contract
Class mapping
| USWDS | Flex | Notes |
|---|---|---|
usa-step-indicator | .flex-step-indicator | Base step indicator |
usa-step-indicator__segments | .flex-step-indicator__segments | Segments list container |
usa-step-indicator__segment | .flex-step-indicator__segment | Individual segment |
usa-step-indicator__segment--complete | data-state="complete" | Completed step segment |
usa-step-indicator__segment--current | data-state="current" | Current step segment |
usa-step-indicator__segment-label | .flex-step-indicator__segment-label | Segment text label |
usa-step-indicator__header | .flex-step-indicator__header | Header containing heading |
usa-step-indicator__heading | .flex-step-indicator__heading | Step heading text |
usa-step-indicator__current-step | .flex-step-indicator__current-step | Current step counter badge |
usa-step-indicator--no-labels | data-variant="no-labels" | Hide segment labels |
usa-step-indicator--counters | data-variant="counters" | Show numbered counters on segments |
usa-step-indicator--counters-sm | data-variant="small-counters" | Show small numbered counters |
usa-step-indicator--center | data-variant="centered" | Center-aligned labels |
Verified properties
background-colorfont-familyIntentional differences
segment state: ours = data-state="complete|current", USWDS = BEM modifier classes (--complete, --current)
We use data attributes instead of BEM modifier classes for state, consistent with our design system conventions.
Behavior promises
- ✓ Complete segments show dark navy bars
- ✓ Current segment shows accent blue bar
- ✓ Incomplete segments show gray bars
- ✓ aria-current="step" on current segment
- ✓ Accessibility audit passes
Source CSS
/* flex-step-indicator — USWDS Step Indicator conformance
Variants: no-labels, counters, small-counters, centered */
.flex-step-indicator {
font-size: var(--flex-text-uswds);
line-height: 1.1;
background-color: var(--flex-color-bg);
margin-block-end: 2rem;
}
/* --- Segments --- */
.flex-step-indicator__segments {
counter-reset: flex-step-indicator;
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
.flex-step-indicator__segment {
flex: 1 1 0%;
counter-increment: flex-step-indicator;
margin-inline-start: 1px;
margin-inline-end: 1px;
/* stylelint-disable-next-line declaration-property-value-allowed-list -- Per-step label width cap. */
max-inline-size: 15rem;
min-block-size: 0.5rem;
position: relative;
/* The colored bar for each segment */
&::after {
background-color: var(--flex-gray-40);
content: "";
display: block;
block-size: 0.5rem;
inset-inline-start: 0;
position: absolute;
inset-inline-end: 0;
inset-block-start: 0;
}
/* Complete segment — dark navy bar */
&[data-state="complete"]::after {
background-color: var(--flex-color-text);
}
&[data-state="complete"] .flex-step-indicator__segment-label {
color: var(--flex-color-text);
}
/* Current segment — accent blue bar */
&[data-state="current"]::after {
background-color: var(--flex-color-accent);
}
&[data-state="current"] .flex-step-indicator__segment-label {
color: var(--flex-color-accent);
font-weight: 700;
}
}
/* --- Segment Labels --- */
.flex-step-indicator__segment-label {
color: var(--flex-gray-cool-60);
display: block;
font-size: var(--flex-text-uswds);
margin-block-start: calc(0.5rem + 0.5rem);
padding-inline-end: 2rem;
text-align: start;
}
/* --- Header --- */
.flex-step-indicator__header {
align-items: baseline;
display: flex;
}
.flex-step-indicator__heading {
color: var(--flex-color-text);
font-size: 1.46rem;
font-weight: 700;
margin: 2rem 0 0;
}
.flex-step-indicator__current-step {
block-size: 2.5rem;
border-radius: 99rem;
inline-size: 2.5rem;
font-weight: 400;
font-feature-settings:
"tnum" 1,
"kern" 1;
background-color: var(--flex-color-accent);
color: var(--flex-color-on-accent);
display: inline-block;
padding: calc((2.5rem - 2ex * 1.1) * 0.5);
text-align: center;
}
.flex-step-indicator__heading-text {
margin-inline-start: 0.5rem;
}
/* --- Variant: No Labels --- */
.flex-step-indicator[data-variant="no-labels"]
.flex-step-indicator__segment-label {
display: none;
}
.flex-step-indicator[data-variant="no-labels"] .flex-step-indicator__segment {
margin-block-start: 0;
margin-inline-start: 1px;
margin-inline-end: 1px;
}
.flex-step-indicator[data-variant="no-labels"]
.flex-step-indicator__segment::before {
display: none;
}
/* --- Variant: Counters --- */
.flex-step-indicator[data-variant="counters"] .flex-step-indicator__segment,
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment {
margin-inline-start: 0;
margin-inline-end: 0;
margin-block-start: calc((2.5rem - 0.5rem) / 2 + 0.25rem);
}
.flex-step-indicator[data-variant="counters"]
.flex-step-indicator__segment::before,
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment::before {
block-size: 2.5rem;
border-radius: 99rem;
inline-size: 2.5rem;
font-feature-settings:
"tnum" 1,
"kern" 1;
background-color: var(--flex-color-bg);
box-shadow:
inset 0 0 0 0.25rem var(--flex-gray-40),
0 0 0 0.25rem var(--flex-color-bg);
color: var(--flex-gray-cool-60);
content: counter(flex-step-indicator);
display: block;
font-weight: 700;
inset-inline-start: 0;
line-height: 0.9;
padding: calc((2.5rem - 2ex * 0.9) * 0.5);
position: absolute;
text-align: center;
inset-block-start: calc((2.5rem - 0.5rem) / -2);
z-index: 100;
}
.flex-step-indicator[data-variant="counters"]
.flex-step-indicator__segment:last-child::after,
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment:last-child::after {
display: none;
}
.flex-step-indicator[data-variant="counters"]
.flex-step-indicator__segment[data-state="complete"]::before,
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment[data-state="complete"]::before {
background-color: var(--flex-color-text);
box-shadow: 0 0 0 0.25rem var(--flex-color-bg);
color: var(--flex-color-on-accent);
}
.flex-step-indicator[data-variant="counters"]
.flex-step-indicator__segment[data-state="current"]::before,
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment[data-state="current"]::before {
background-color: var(--flex-color-accent);
box-shadow: 0 0 0 0.25rem var(--flex-color-bg);
color: var(--flex-color-on-accent);
}
.flex-step-indicator[data-variant="counters"]
.flex-step-indicator__segment-label {
margin-block-start: calc((2.5rem + 0.5rem) / 2 + 0.5rem);
}
/* --- Variant: Small Counters --- */
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment {
margin-block-start: calc((1.5rem - 0.5rem) / 2 + 0.25rem);
}
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment::before {
block-size: 1.5rem;
inline-size: 1.5rem;
font-size: 0.93rem;
padding: calc(0.25rem + 1px);
inset-block-start: calc((1.5rem - 0.5rem) / -2);
}
.flex-step-indicator[data-variant="small-counters"]
.flex-step-indicator__segment-label {
margin-block-start: calc((1.5rem + 0.5rem) / 2 + 0.5rem);
}
/* --- Variant: Centered --- */
.flex-step-indicator[data-variant="centered"]
.flex-step-indicator__segment-label {
text-align: center;
padding-inline-end: 0;
}
A digital services project by Flexion