Accessible Styled Form Controls

Styled Progress Bar

Last updated:

Cross-browser styling for the HTML progress bar.

Pattern Demo

File Uploaded:

Pattern Details

Pattern Markup
<label for="tasks_comp2">
  Tasks Completed:
  <progress class="progress-bar"
    id="tasks_comp2"
    value="50" max="100"></progress>
</label>

<span id="file_status2">
  File Uploaded:
</span>
<progress class="progress-bar"
  aria-labelledby="file_status2"
  value="70" max="100"></progress>

<progress class="progress-bar"
  aria-label="Delivery Status"
  value="80" max="100"></progress>

Unlike many other form elements, a progress element is read-only, and the progress bar is modified by the completion of tasks by a user, or the application itself.

A task can refer to user flows, like a user's current progress in a sign up flow, or a task being performed by an application, or server. For example, using a progress bar to indicate the application updating after a form submission, or indicating the progress of a file upload within an application's UI.

For indicating the state of a finite gauge, such as available diskspace, a meter would be more appropriate.

Styling a progress element

The progress element has support in all modern browsers, including Internet Explorer. The only catch to styling it is it requires the use of vendor prefixed selectors. Though, compared to the range element, there aren't that many to worry about.

Largely the prefixed selectors to be concerned with are the following:

::-webkit-progress-bar
Setting the background style for Webkit
::-ms-fill
Style for progress indicator in MicroSoft browsers
::-moz-progress-bar
Style for progress indicator in Firefox
::-webkit-progress-value
Style for progress indicator in webkit browsers

Additionally there are the ::-webkit-progress-inner-element and :indeterminate selectors. But they are not used for the styled progress elements shown here.

Affects on Screen Reader Announcements?

Even though the progress element has good accessibility support and feature implementation, not all screen readers have full support for the element, and styling a progress element can have detrimental affects in some instances.

Note: progress bars are not meant to be focusable elements, so the following tests were performed with the virtual cursor.

JAWS 2018 + Internet Explorer 11

A styled or unstyled progress element is not announced when using JAWS with Internet Explorer.

JAWS will read the visible text next to the progress bar, but will skip over the progress bar when navigating with the virtual cursor.

JAWS 2018 + Firefox 63 (nightly)

A styled or unstyled progress element is announced the same way when using JAWS with Firefox.

The virtual cursor first stops on the visible label of the progress bar and announces the content. The virtual cursor then announces the progress bar and it's current value, ##% progress bar..

JAWS 2018 + Chrome (latest)

Unstyled progress bars do not convey their accessible name, and styled progress bars convey no information at all, with JAWS and Chrome.

NVDA 2018.2.1 + Firefox 63 (nightly)

When NVDA virtual cursor focuses a styled progress bar with an accessible name provided by a label, NVDA will announce:

Clickable [Accessible name (from visible label)], progress bar ##%

When NVDA virtual cursor focuses a styled progress bar with an accessible name provided by aria-labelledby or aria-label, NVDA will announce:

[Accessible name (from visible label)], progress bar ##%

NVDA 2018.2.1 + Chrome (latest)

When NVDA virtual cursor focuses a styled or unstyled progress bar with an accessible name provided by a label, NVDA will announce:

[Accessible name (from visible label)], progress bar [Accessible name]

If an accessible name is provided by an aria-label or aria-labelledby then NVDA will ignore the current value and announce the accessible name in place of the value.

[Accessible name (if there's a visible label)], progress bar [Accessible name (from aria-label or aria-labelledby)]

VoiceOver + Safari 11.1.1 on macOS High Sierra

Styling progress bars causes their announcement with VoiceOver to be altered and result in more focus stops for a user. A styled progress bar will no longer recognize its accessible name from a label. If using an aria-label or aria-labelledby with a progress bar, VoiceOver will announce the element as a group. A user will then need to enter the "group" to hear the accessible name and current value of the progress bar. An unstyled progress bar has no "group" announcements, regardless of how the accessible name is applied to the progress bar.

A styled progress bar, with a visible label, will be announced as:

Focus stop 1: [Accessible name (visible label)]
Focus stop 2: ## percent, progress indicator

A styled progress bar, with an aria-labelledby, will be announced as:

Focus stop 1: [Accessible name (visible label)]
Focus stop 2: [Accessible name], group
Focus stop 3: ## percent, progress indicator
Focus stop 4: end of [Accessible name], group

A styled progress bar, with an aria-label, will be announced as:

Focus stop 1: [Accessible name], group
Focus stop 2: [Accessible name], ## percent, progress indicator
Focus stop 3: end of [Accessible name], group

Note that VoiceOver + Chrome doesn't fair much better, as styled progress bars do not become groups, but are announced as "indeterminate progress indicator" regardless of their set value.

VoiceOver + Safari on iOS 11.4

Regardless of styled or not, VoiceOver does not announce the role of a progress bar when it receives focus.

Unstyled progress bars will announce their accessible name and current value if they are focused by VoiceOver. Styled progress bars will not announce their accessible name, unless they explicitly have an aria-label, and they will become undiscoverable when searching by touch.

A styled progress bar, with a visible label, will be announced as:

Focus stop 1: [Accessible name (visible text)]
Focus stop 2: ##%

A styled progress bar, with an aria-label, will be announced as:

[Accessible name], ##%

TalkBack (Android Accessibility Suite 6.2) + Android Chrome

TalkBack has no issues with announcing the accessible name of a progress bar, however regardless of a progress bar being styled or not, TalkBack paired with Chrome does not announce the current value of a progress bar.

Usage note:

Though the progress element is largely reporting the correct information to browsers, screen readers have quite a few kinks in how they announce the element to users.

At the time of testing, a styled progress bar won't be fully accessible in all screen reader and browser pairings. Instead it may be more appropriate to simply treat the progress bar as a visual decoration, hide it from screen readers, and provide visually hidden text as a means to consistently convey the information.