Styled Progress Bar
Published:
Last updated:
Cross-browser styling for the HTML progress bar.
Pattern Demo
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 semantically 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, 2019 + 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, 2019 + Firefox 63, 65.0.2
-
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.
.When retesting with JAWS 2019 and Firefox 65.0.2, a progress bar will not announce an accessible name provided by an
aria-label
. - JAWS 2018, 2019 + Chrome (latest)
-
Unstyled progress bars do not announce their accessible name, and styled progress bars convey no information at all.
- NVDA 2018.4.1 + Firefox 65.0.2
-
When NVDA virtual cursor focuses a styled progress bar with an accessible name provided by a
label
, NVDA will announce:First stop is the label element:
Clickable [Accessible name]
Second stop is the progress element:
progress bar ##%
When NVDA virtual cursor focuses a styled progress with an accessible name from
aria-labelledby
oraria-label
, NVDA will announce:[Accessible name (from aria labeling method)], progress bar ##%
- NVDA 2018.2.1 + Chrome (latest at time of testing)
-
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
oraria-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
oraria-labelledby
)]The current value of the progress bar is not announced
- NVDA 2018.4.1 + Chrome (72)
-
Similar to 2018.2.1, the primary difference is that now styled progress bars will announce as "half checked", regardless of what their actual value is.
- VoiceOver + Safari 13.1.2 on macOS Catalina
-
An unstyled progress bar will receive its accessible name from a
<label>
element. If styled, the association between the label and the progress indicator will break, resulting in the progress bar having no accessible name.If using
aria-label
oraria-labelledby
to add an accessible name to a styled progress bar, it will be announced as a "group". A user will then need to navigate into the named "group" to hear the "progress indicator" role and value announcement.Previous results
VoiceOver + Safari 11.1.1 on macOS High Sierra
VoiceOver + Safari 12.0.3 on macOS Mojave
Styling progress bars causes their announcement with VoiceOver to be altered and result in more VO focus stops for a user. A styled progress bar will no longer recognize its accessible name from a
label
. If using anaria-label
oraria-labelledby
with a progress bar, VoiceOver will announce the element as agroup
. 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, 12.1.4, 14.4.2
-
Regardless of if they are styled or not, VoiceOver does not announce the role of a progress bar when it receives VO focus.
Unstyled progress bars will announce their accessible name and current value if they are swiped to with VoiceOver enabled. If using a
<label>
element to provide the progress bar its accessible name, VoiceOver will purposefully skip over the text label and instead directly focus the progress bar and announce its name and value as a single VO focus stop.In contrast, styled progress bars will not behave as described above, even if they are properly associated with a
<label
. Rather VO will announce the label and the progress value as separate swipe stops. A<progress>
can be forced to announce an accessible name, by giving it anaria-label
, however this will oddly make the element unable to be discovered when searching by touch (i.e., dragging your finger around the screen to move VO focus).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 (when swiped to):[Accessible name], ##%
An unstyled progress bar with an associated
<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.