Skip to main content

Notes

Accessible Checkout Step Indicators: What aria-current="step" Actually Requires

Quietramp ·

Accessible Checkout Step Indicators: What aria-current=“step” Actually Requires

Quick answer: A multi-step checkout tracker — “Cart → Shipping → Payment → Review,” with the current step visually highlighted — needs aria-current="step" on the element representing where the shopper currently is. The WAI-ARIA 1.2 specification defines it directly: step is a listed token value of the aria-current attribute, described as representing “the current step within a process,” and the spec’s own usage note names this exact component: “a step token used to indicate a link within a step indicator for a step-based process, where the link is visually styled to represent the current step.” Without it, a screen reader user gets a row of text or links that all sound identical, with no indication which one is “you are here.”

This article covers technical accessibility practice, not legal advice — it explains what a step-indicator component needs to meet WCAG 2.1 AA and how to implement it, not whether a specific site carries legal risk.

Why a color change alone doesn’t communicate anything

A typical checkout step tracker marks the current step with a filled circle, a bolder color, or an underline, and marks completed steps with a checkmark. All of that is CSS and an icon swap — real information for a sighted user, and nothing at all for a screen reader user unless the markup says so explicitly. This is the same gap WCAG SC 1.3.1 Info and Relationships (Level A) exists to close: “information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.” A shopper on a screen reader tabbing through “Cart, Shipping, Payment, Review” — four links or list items that all read the same way — has no way to tell that “Shipping” is the step they’re currently on, versus a step they’ve already completed or haven’t reached yet.

The token built for exactly this case

MDN’s aria-current reference doesn’t describe this in the abstract — it names the e-commerce case directly. Its description of the step value: “Represents the current step within a process such as the current step in an enumerated multi step checkout flow.” Its usage guidance is just as specific: “In a multi step based process with a step indicator such as a multi-page survey or a multi step checkout or registration process, when the current step icon is visually different to represent that it is the current step, that icon’s container should have aria-current="step" for assistive technology users who may not be able to ‘see’ the visual difference.”

step is one of a fixed set of enumerated aria-current tokens defined in the WAI-ARIA 1.2 spec — page, step, location, date, time, true, and false — each aimed at a different kind of “current item in a set.” page is what Quietramp’s breadcrumb-navigation article covers, for the current page in a breadcrumb trail. step is the same underlying mechanism aimed at a different kind of set: not pages in a site hierarchy, but steps in a single task. Per the spec, “authors SHOULD only mark one element in a set of elements as current with aria-current” — one step per tracker, not the current step plus every completed one.

One implementation detail worth flagging directly: aria-current isn’t usable everywhere. MDN’s own reference lists it as unsupported “for elements with the role of gridcell, option, row and tab” — a step indicator built from tab-like markup (role="tab" on each step) can’t carry aria-current on those elements; a plain list or set of links doesn’t have that restriction.

The pattern in practice

The APG doesn’t publish a dedicated “stepper” design pattern the way it does for breadcrumbs, tabs, or dialogs — a step indicator is closer to a specialized navigation list than a full interactive widget, so the fix is markup and one attribute, not a keyboard model to build from scratch:

<nav aria-label="Checkout progress">
  <ol>
    <li><a href="/cart">Cart</a></li>
    <li aria-current="step"><a href="/checkout/shipping">Shipping</a></li>
    <li><span>Payment</span></li>
    <li><span>Review</span></li>
  </ol>
</nav>

A few details in that markup are load-bearing, not decorative:

  • aria-current="step" sits on the current step, not on every step. If the tracker’s real visual behavior lets a shopper click back to a completed step, that step stays a real <a>; a step not yet reachable (Payment, Review, before Shipping is done) is reasonably rendered as plain text rather than a dead link — a <span>, not an <a href="#"> that goes nowhere.
  • The list stays a real <ol>, for the same SC 1.3.1 reason a plain-text breadcrumb trail fails without one: a run of <div>s or bare links with CSS-only spacing gives a screen reader no indication there are four related items in a specific order.
  • The <nav> gets its own accessible name (aria-label="Checkout progress"), distinguishing it from the site’s primary navigation landmark the same way a breadcrumb’s <nav> does.

Three failures that show up before aria-current is even relevant

aria-current="step" is the finishing touch on a step indicator, not the whole fix. It’s common to find one of these three problems underneath it:

No accessible name on icon-only steps. Some trackers render each step as a numbered circle with no visible text label at all — just “1,” “2,” “3” inside styled dots, with the step names shown only as a tooltip or omitted entirely on mobile. WCAG SC 4.1.2 Name, Role, Value (Level A) requires that “for all user interface components… the name and role can be programmatically determined” — a step represented only by a number, with the actual step name never exposed in text or an aria-label, gives a screen reader user “2” with no way to know that means “Shipping.”

Non-descriptive step labels. WCAG SC 2.4.6 Headings and Labels (Level AA) requires that “headings and labels describe topic or purpose.” “Step 2” describes a position, not a purpose — pairing the number with the actual step name (“Step 2 of 4: Shipping,” not just “Step 2”) is what actually orients a user, sighted or not, to what happens on that step.

A tracker built entirely from background images or a canvas/SVG graphic, with no underlying text or list markup at all. This fails SC 1.3.1 outright — there’s no structure to programmatically determine because there’s no markup describing one, regardless of how the visual design looks.

What a scan catches, and what a person has to check

An automated scanner can confirm a step indicator has list markup and that link text isn’t empty. It generally can’t confirm that exactly one step carries aria-current="step" at the right moment (a common bug: the attribute stays hard-coded on step one instead of updating as the shopper progresses), or that a screen reader actually announces “current step” language when it lands on that item — both require walking the flow with a screen reader, not just parsing the rendered DOM once.

FAQ

Does every step in the tracker need to be a link? No. The current step and any completed step a shopper can navigate back to are reasonably links; a step that hasn’t been reached yet is often better as plain text, since a link that goes nowhere useful (or skips required steps) creates its own confusion.

Is aria-current="step" required for WCAG 2.1 AA conformance? aria-current itself isn’t a named WCAG success criterion — it’s an ARIA attribute, one documented technique among several for satisfying SC 4.1.2’s requirement that current state be programmatically determinable. A step indicator could pass 4.1.2 a different way (an aria-label="Shipping, current step" on the element, for example), but aria-current="step" is the purpose-built, standard mechanism for it.

Does this overlap with the breadcrumb article’s aria-current="page" pattern? They’re the same underlying attribute applied to a different kind of set — a breadcrumb tracks position in a page hierarchy (page), a step indicator tracks position in a single task or process (step). The mechanism is identical; which token applies depends on what the “current item” is current within.

Get your checkout flow checked by a person, not just a parser

Quietramp’s $890 audits include a manual pass through checkout-specific components like step indicators — confirming the current-step attribute actually updates as a real shopper moves through the flow, not just that a <nav> and <ol> exist somewhere in the markup. See a real sample report or check pricing — $890 one-time, $99/month for ongoing re-checks after fixes ship.


This is educational content about technical accessibility practice, not legal advice. Meeting WCAG 2.1 AA does not constitute a legal compliance determination under the ADA or any other standard — consult qualified counsel for legal risk questions.

This article was drafted with AI assistance and reviewed by a person for accuracy before publication.

← Back to Notes