Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use the native HTML <progress> element for a task’s progress. Give it a label, set max and value for determinate progress, and omit value when the amount of progress is unknown. Its basic semantics are broadly supported; test your CSS in the actual browsers and versions your project supports because native controls may not look identical.
Build a labeled progress bar with HTML
For a task that has a known amount of work, use a <progress> element with both a maximum and a current value:
<label for="upload-progress">Upload progress</label>
<progress id="upload-progress" max="100" value="45">45%</progress>
Here, max="100" makes the values percentage-like, so value="45" represents 45 out of 100. The default maximum is 1, so a fractional value also works: <progress value="0.45"></progress>. A specified max must be greater than zero, and value must be between zero and the maximum.
The text inside the element is fallback content; it does not provide the progress bar’s accessible name. Use an associated visible <label>, as above, or provide a programmatic name with aria-label or aria-labelledby. If you show a separate percentage or status message, keep it synchronized with the actual progress value.
#1 Best Overall
Represent indeterminate progress
When work is underway but you cannot calculate how much is complete, omit the value attribute:
<label for="upload-progress">Uploading file</label>
<progress id="upload-progress" max="100"></progress>
Do not use value="0" to mean “unknown”: zero is a determinate value. If JavaScript changes an existing determinate progress element to indeterminate, remove the attribute:
const progress = document.querySelector('#upload-progress');
progress.removeAttribute('value');
The WHATWG HTML Standard specifies removing the value attribute to make a progress bar indeterminate.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
Update progress safely with JavaScript
Update the element’s value as work advances, keeping it within the range from zero through its maximum. If visible status text is present, update that too:
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteconst progress = document.querySelector('#upload-progress');
const status = document.querySelector('#upload-status');
function setProgress(completed, total) {
if (total <= 0) throw new Error('Total work must be greater than zero');
const value = Math.min(Math.max(completed, 0), total);
progress.max = total;
progress.value = value;
status.textContent = `${Math.round((value / total) * 100)}% complete`;
}
For this example, include a status element in the page:
<label for="upload-progress">Upload progress</label>
<progress id="upload-progress" max="100" value="0">0%</progress>
<p id="upload-status">0% complete</p>
When the amount of work is not known, leave value absent rather than reporting a guessed percentage. If the task later becomes measurable, set a valid maximum and value.
Rank #3
Associate progress with a region being updated
If the bar describes a page region that is currently changing, connect the two with aria-describedby and mark the region busy while the update is in progress:
<section id="upload-panel" aria-busy="true" aria-describedby="upload-progress">
<label for="upload-progress">Uploading file</label>
<progress id="upload-progress" max="100" value="45">45%</progress>
<p>Upload details appear here.</p>
</section>
Set aria-busy="false" when the region’s update finishes. The progress element already has an implicit progressbar role; a custom widget does not get those semantics automatically.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Style the bar without relying on identical browser rendering
Start with native <progress> semantics, then add visual styling only after checking how it renders in your supported browsers. Native control rendering differs, and browser-specific pseudo-elements do not have a single styling recipe established here that can be promised to work identically everywhere. Avoid claiming pixel-identical results unless you have verified the exact browsers and versions your project targets.
Rank #4
Use a project-specific compatibility check rather than assuming that broad support for the element guarantees matching appearance. Include the states your interface uses: empty, partial, complete, and indeterminate. Also confirm that the accessible name and current state are conveyed correctly with the assistive technologies in your support matrix.
Native progress or a custom progress bar?
| Approach | Semantics and accessibility | Visual control | Best fit |
|---|---|---|---|
Native <progress> |
Provides task-progress semantics and an implicit progressbar role; give it an accessible name. | Styling and appearance can vary by browser. | Most task-progress indicators. |
| Custom markup | You must supply the accessible name, progressbar role, and correctly maintained value and state. | Allows custom markup, but does not remove the need to test rendering and accessibility. | Only when the native control cannot meet a specific interface requirement and the team can maintain its semantics. |
Use <meter> for a scalar measurement, such as a value within a known range, rather than for completion of a task. A progress indicator communicates work completed or underway; a meter communicates a measurement.
Test browser compatibility and troubleshoot common problems
The basic <progress> element is widely available. MDN describes it as available across browsers since July 2015, but that is not a guarantee for every older browser version or for identical styling. Your project’s minimum browser versions and assistive-technology combinations determine what you need to validate.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Best Value
- The bar looks different between browsers: Native controls may use browser-specific rendering. Check the required browsers and versions, adjust the styling for those targets, and do not assume one vendor-specific rule works everywhere.
- The bar appears empty even though work has not started: A value of zero means determinate progress at zero. For work with unknown progress, remove the
valueattribute. - The value is rejected or does not represent the intended amount: Check that
maxis greater than zero and thatvalueis a valid number between zero andmax. Remember that the default maximum is one. - A screen reader does not announce what the bar measures: Add a visible associated
<label>, or provide an accessible name witharia-labeloraria-labelledby. Text nested inside<progress>is fallback content, not its accessible name. - A custom bar is missing progress semantics: Prefer native
<progress>where possible. A custom widget needs progressbar semantics and state values that are updated accurately; omitaria-valuenowwhen a custom progressbar is indeterminate.
Test the actual minimum browser versions your project supports, including determinate values at zero, between zero and the maximum, and at completion, plus indeterminate state if used. Check both visual presentation and the accessible name and announced state.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Or skip the browser setup
If you want screenshots to review how a page renders, ScreenshotNeo can capture the target URL; screenshots are useful for visual inspection, but they do not replace testing the relevant browsers or assistive technologies. For example, a cURL request is:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
See the ScreenshotNeo documentation for API details. ScreenshotNeo accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response indicates the page verdict and billing status in headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000.
Sign up for ScreenshotNeo’s free plan to try 1,000 screenshots a month with no card.
Free tools Windows power users keep installed
One-click scans. No signup required.
Frequently Asked Questions
Should I use <progress> or <meter> for a task that is 45% complete?
Use <progress> for completion of a task. Use <meter> for a scalar measurement within a known range.
Does <progress> need an explicit ARIA role?
No. The native element has an implicit progressbar role. Give it an accessible name; custom progress markup requires its own progressbar semantics.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




