The HTML progress element
For an upload, download, or any other task with measurable progress, HTML already has the right element. A <progress> element needs both opening and closing tags:
<progress value="10" max="100"></progress>
value must be zero or greater and no larger than max. If max is omitted, it defaults to 1; when present, it must be greater than zero. Leave out value when the amount of progress is unknown and you need an indeterminate indicator.
Browser support was already good in 2020, with support beginning in Safari 6 and Internet Explorer 10. Use <meter> instead when you are showing a measurement, such as disk usage, rather than the completion of a task.
Styling is browser-specific
Browsers give <progress> their own native appearance. The element selector handles the outer box:
progress {
background-color:#ddd;
border:0;
height:20px;
border-radius:5px;
}
The filled portion needs vendor-specific pseudo-elements:
/* Firefox */
progress::-moz-progress-bar { background: #ddd; }
/* WebKit & Blink */
progress::-webkit-progress-bar { background: #ddd; }
progress::-webkit-progress-value { background: #000; }
Native styling is a reasonable default, and I would keep it unless the bar genuinely clashes with the rest of the interface. If you customise it, check the result in more than one browser.