Skip to content
easeweb
Search topics

Progress bars and meters that screen readers can't read

An upload bar is drawn with styled divs, or given a progressbar role with no name and a value that never moves, so a screen reader hears nothing of how far along it is or when it ends.

WCAG 2.2
SC 4.1.2ASC 4.1.3AA· new in 2.1
Required by
Section 508 · EN 301 549 (EU)
Broken <div class="bar"><div class="fill" style="width: 60%"></div></div>
The accessibility problem illustrated: No vision:Is my file still uploading?
01

The problem

Screen reader users start an upload and can't tell how far along it is, whether it is still going, or when it has finished.

02

Try it

Press Enter on Upload and listen while the bar fills.

The panel shows what a screen reader announces during the upload, and what it reads if you move to the bar. Do you hear how far along it is, and when it ends?

Broken Can you fix this?

Uploading report.pdf

Screen reader says:

(Press Upload)

A recreated demo. The broken version is intentionally inaccessible.

03

The fix

Give the bar a name and a value that moves with it, and announce its milestones and its end.

  1. 1Say what each bar measures, in its name or in the text beside it.
  2. 2Set the value from the code that draws the fill.
  3. 3Announce milestones and the end in a status region, not every percent.
Before

A bar drawn with divs

<p>Uploading report.pdf</p><div class="bar"><div class="fill" style="width: 0%"></div></div><p class="done" hidden>Uploaded</p>
After

A native progress element

<label for="upload-bar">Uploading report.pdf</label><progress id="upload-bar" max="100" value="0">0%</progress><p class="done" hidden>Uploaded</p><p id="upload-status" role="status" class="visually-hidden"></p>

Why this fix: Use native HTML first

Fixing this with an AI coding assistant? Get this guide as Markdown, or get every guide in your coding agent.

04

Design ideas

A bar can be soft and still be read.

Eight ways to draw how far something has got, two of them moving. The guide’s fixes make each one readable to a screen reader; these are about whether everyone else can see it.

Passes

  • Uploading report.pdf

    Fill at 3:1 or more against its track #1f5fa8 on a #e6e9ee track is 5.29:1. When the fill is the only place the value shows, it is a graphic that carries meaning, so it needs 3:1 under 1.4.11.
  • Uploading report.pdf

    Soft bar, with the percentage written beside it The pale fill is only 1.47:1 against its track, but “60%” says the value in text, so the fill is no longer needed to understand it. The bar can stay as soft as the design wants.
  • Uploading report.pdf

    Ring with the number in the middle The same value as an arc, for a compact card or a phone. The number carries the value, and the arc keeps 5.29:1 against its track anyway.
  • Delivery detailsStep 2 of 4

    Segments with the step written out For a checkout or a set-up flow, where progress is steps rather than percent. “Step 2 of 4” says where you are; the segments are a summary of it.
  • Uploading report.pdf

    Fill that glides to each new value Press Replay. The fill eases over 0.4 seconds each time the value changes, and stops when the value does, so it moves only to show progress. Under a reduced-motion setting it jumps instead.

Fails

  • Uploading report.pdf

    Thin pale bar, nothing elseWCAG 1.4.11 The fashionable 4px bar: #a8c4e6 on #e6e9ee, 1.47:1, and no text. The fill is the only place the value shows, and many people can’t tell where it ends.
  • report.pdf

    Turns red when the upload failsWCAG 1.4.1 Colour alone says the upload failed: the bar looks the same as a running one to people who don’t see red. Write “Upload failed” and what to do next beside it.
  • report.pdf uploaded

    Stripes that keep moving after it finishesWCAG 2.2.2 The upload is done, but the barber-pole stripes go on sliding beside the rest of the form, with nothing to pause them. This sample stops after a few seconds; the pattern itself never does.
05

Verify the fix

4 checks, no mouse.

Test with: Screen reader, Keyboard

0 of 4 checked

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the upload code or the progress component changes.

Limits

Screen readers differ in how they report progress bars: some read the value as a percentage, some beep, and some speak only when the person moves to the bar, and their support for meters is weaker still. This guide covers one bar for one process on one page. A spinner or a wait with no amount is covered in loading spinners that screen readers never announce, and a message that isn't about progress, such as "Draft saved", in status messages that are shown but never announced. Test real uploads, slow and failing ones included, with the screen readers your users use.

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

Keep this fixed as your code changes.

Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.

How retests work