The <progress> element
The <progress> tag shows how far a task has got, such as a file upload or a multi-step form, as a progress bar. Set value for the amount done and max for the total (1 by default). Leave out value to show an indeterminate bar, which means work is happening but the remaining time is unknown.
Last updated: October 3, 2026
Quick facts
| Category | Flow content, phrasing content, labelable, palpable content |
| Content model | Phrasing content, but no <progress> inside |
| Tag omission | Neither the start nor the end tag can be omitted |
| Permitted parents | Any element that accepts phrasing content |
| DOM interface | HTMLProgressElement |
Syntax
Live example
Edit the code below and watch the preview update instantly.
Attributes
| Attribute | Description |
|---|---|
| value | How much of the task is done, between 0 and max. Leave it out for an indeterminate bar |
| max | The total amount of work. Must be greater than 0; defaults to 1 |
Common examples
An upload progress bar
Update the value as data arrives; the bar fills in automatically.
Steps in a form
Show how far someone is through a multi-step checkout.
A styled progress bar
Browsers use their own look; vendor pseudo-elements and accent-color let you restyle it.
<progress> vs a <div> progress bar
Many sites build progress bars from two <div>s: a grey track and a coloured inner bar whose width changes. It looks the same, but screen readers see nothing unless you add role="progressbar" and keep aria-valuenow, aria-valuemin and aria-valuemax updated yourself.
<progress> has that meaning built in — screen readers announce the percentage automatically. The div approach gives total design freedom; the element is less work and accessible by default.
| <progress> | <div> bar | |
|---|---|---|
| Accessible by default | Yes | No (needs ARIA) |
| Styling | Limited, browser-specific | Full control |
| Code needed | One element | Two divs + ARIA + JS |
Common mistakes to avoid
- Using progress for measurements. Disk usage or a rating isn’t “progress”; use <meter>.
- No label. Add a
<label>oraria-labelso people know what is loading. - A value larger than
max. It’s clamped to full, which can hide bugs in your code. - Setting
value="0"when progress is unknown. Leavevalueout to show an “indeterminate” busy animation instead.
Accessibility & SEO tips
- Also show the percentage as text (“45%”) next to the bar, for people who can’t judge the bar length.
- For long waits, tell people what is happening (“Uploading 3 of 10 photos”) — progress bars reduce frustration and abandonment.
- Use
aria-busy="true"on the area being updated while it loads. - Respect
prefers-reduced-motionby toning down animated or striped bars for visitors who prefer less movement.
Browser support
Supported in all modern browsers, including Chrome, Edge, Firefox, Safari and their mobile versions. It was introduced with HTML5, and only very old browsers such as Internet Explorer 8 needed workarounds.