How to make a progress bar
Short answer
There is a tag for progress — progress:
<label>Uploading <progress value="70" max="100">70%</progress></label>Without the value attribute the bar becomes "indeterminate" — a running animation for when it is unknown how much is left.
Styling progress
accent-color changes the color. For full control reset the look with appearance: none and style the bar's parts — they have different names in different browsers:
<style>
.bar { appearance: none; width: 240px; height: 12px; border: none; border-radius: 6px; background: gainsboro; overflow: hidden; }
.bar::-webkit-progress-bar { background: gainsboro; }
.bar::-webkit-progress-value { background: seagreen; border-radius: 6px; }
.bar::-moz-progress-bar { background: seagreen; border-radius: 6px; }
</style>
<progress class="bar" value="45" max="100">45%</progress>A bar on a div
If you need a fully custom look, build the bar from two blocks and tell screen readers the value with ARIA:
<div role="progressbar" aria-valuenow="3" aria-valuemin="0" aria-valuemax="5" aria-label="Step 3 of 5" style="height: 8px; background: lavender; border-radius: 4px;">
<div style="width: 60%; height: 100%; background: linear-gradient(90deg, mediumpurple, royalblue); border-radius: 4px;"></div>
</div>Common mistake
Using progress for a value that is not task progress — such as disk usage or a rating. For such measurements there is the meter tag: it can color low and high values differently.
Functions used in this recipe
- <progress> — A progress bar for a task: an upload, the steps of a form.
- <meter> — A gauge for a value within a known range: battery, usage, a rating.
- accent-color — The accent color of built-in form controls: checkboxes, radio buttons, sliders and progress bars.