Making a step progress indicator accessible for screen readers

Are the steps static or can the user click on a previous step to go back?

If the progress indicator is interactive, then enclose the whole thing in a <nav> element. Your progress indicator would be similar to a breadcrumb trail. The <nav> should also have an aria-label and the current step in the process should have aria-current. So it might look something like:

<nav aria-label="progress">
  <ul class="progress-tracker progress-tracker--text progress-tracker--center">
    <li class="progress-step is-complete">
      ...
    </li>

    <li class="progress-step is-complete">
        ...
      </li>

    <li class="progress-step is-active" aria-current="true">
        ...
      </li>

    ...
  </ul>
</nav>

However, your code snippet didn't include any links so I'm guessing your progress indicator is static and not interactive. In that case, don't use a <nav>, because you can't navigate with your indicator, but you could still group the elements together. Having an unordered list is a type of grouping, but sometimes a screen reader will not read the aria-label on a list.

<ul aria-label="progress">

You could work around the issue by having:

<div role="group" aria-label="progress">
  <ul>
    <li>
      ...
    </li>
  </ul>
</div>

(essentially replacing the <nav> in the first example with <div role="group">.

Since your progress indicator is a series of steps, using an ordered list <ol> would have better semantic information. You can style the list so the default numbers of a <ol> are not displayed (similar to how you're not showing bullet points with the <ul>).

And finally, I would add some "hidden" text for the screen reader to say if the step is completed or not. Visually, you have blue circles for completed steps, an open circle for the active step, and gray circles for not completed. That's all done with CSS (your "is-complete" and "is-active" classes). That same context should be conveyed to screen readers. The open circle ("is-active") is conveyed with the aria-current attribute. Use a "sr-only" type class to add text for a screen reader. (See What is sr-only in Bootstrap 3?)

<div role="group" aria-label="progress">
  <ol class="progress-tracker progress-tracker--text progress-tracker--center">
    <li class="progress-step is-complete">
      <span class="sr-only">completed</span>
      ...
    </li>

    <li class="progress-step is-complete">
      <span class="sr-only">completed</span>
      ...
    </li>

    <li class="progress-step is-active" aria-current="true">
      ...
    </li>

    <li class="progress-step">
      <span class="sr-only">not completed</span>
      ...
    </li>
    ...
  </ol>
</div>

In summary, the minimal changes you need are to:

  • maybe switch from <ul> to <ol>
  • add "sr-only" text to the "completed" and "not completed" items
  • add aria-current to the current step

I disagree with the answers that were previously added to this question.

The correct way of identifying the current step is with aria-current="step".

While aria-current="page" is valid, is meant to be used in a set of links (for exemple, a breadcrumbs widget or a pagination widget).I highly recommend reading more about the aria-current attribute, including its possible values and when to use it. Your example would then look like follows:

<ol>
  <li>Step 1 ... </li>
  <li>Step 2 ... </li>
  <li aria-current="step">Step 3...</li>
  <li>Step 4 ... </li>
  <li>Step 5 ... </li>
</ol>

Note: I also recommend you use an <ol> instead of an <ul> as this list of steps has an order.