In HTML, what is the difference between the <progress> and <meter> elements, and when do you use each?
answer
- one is a task, one is a reading
- "is it done yet?" decides it
- omit value for the unknown-duration state
- low, high, optimum shape the gauge
- neither names itself
basics
~20 sThe progress element shows how far a task has advanced toward completion, and shows an indeterminate state when its value is omitted. The meter element shows a scalar measurement inside a known range, such as disk usage or a score, which is not moving toward any finish.
solid answer
~50 sThey look similar and mean different things. `<progress value="70" max="100">` represents completion of a task — an upload, an install — and is the element you update over time; leave `value` out and it renders the indeterminate "working" state. `<meter value="0.6">` represents a measurement in a known range that is not going anywhere in particular: disk usage, a rating, remaining quota. `<meter>` also takes `min`, `max`, `low`, `high` and `optimum`, which let the browser show whether the current reading is in a good or bad band. Practically: if the answer to "is it done yet?" is meaningful, it is a progress bar; if the value simply *is* what it is, it is a meter. Both are labelable, so give each one a real label — a bar with no name announces a number with no meaning.
code
html · 5 lines<label for="job">Import</label>
<progress id="job" value="0.4">40%</progress>
<label for="quota">API quota used</label>
<meter id="quota" value="0.9" low="0.5" high="0.85" optimum="0">90%</meter>go deeper
Be able to say that progress tracks a task moving toward completion while meter reports a measurement within a known range, and give one concrete example of each. Know that both need a label.
Explain the defaults — max of 1, an omitted value meaning indeterminate — and what low, high and optimum let the browser express. Be ready to say the two elements are exposed to assistive technology through different roles.
Show that you choose these for the meaning they broadcast, not the visuals: the wrong element misreports state to assistive technology, and naming, indeterminate states and update announcement are decisions rather than accidents.
Be prepared to argue when native output elements suffice and when a design system's custom gauge is worth its ongoing cost, and to set the rule that any status indicator ships with an accessible name and a defined indeterminate state.
## Two bars, two meanings The visual similarity is a trap. These elements encode different claims about what the number means. **`<progress>` is about a task.** It says: something is running, and this is how much of it is finished. There is an end state, and the value is expected to travel toward it. ```html <label for="upload">Uploading</label> <progress id="upload" value="32" max="100">32%</progress> ``` `max` defaults to 1, so `value="0.32"` with no `max` means the same thing. Omit `value` entirely and you get the **indeterminate** state — the animated "working, duration unknown" bar. That is the correct markup for "we have started and cannot estimate", and it is a genuinely useful state most hand-built spinners never distinguish from a real percentage. The text inside the element is a fallback for browsers that do not support it; supporting browsers do not display it. It is not a label. **`<meter>` is about a measurement.** It says: here is a value on a known scale, right now. Disk space in use, a review score, the fraction of a quota consumed, a temperature within an operating band. Nothing is completing. ```html <label for="disk">Disk used</label> <meter id="disk" value="0.82" low="0.5" high="0.8" optimum="0.1">82%</meter> ``` Beyond `value`, `min` and `max` (defaulting to 0 and 1), `<meter>` takes three attributes that describe the *shape* of the scale: `low` and `high` mark the boundaries of the middle band, and `optimum` says where the good end is. From these, browsers colour the gauge to indicate whether the current reading is in the preferred, suboptimum or worst band. That is the part people forget exists — the element does not just draw a bar, it can express whether the number is good news. ## Choosing between them Ask whether "is it done yet?" is a sensible question about the value. - Upload, install, multi-step wizard completion, a batch job: **progress**. - Disk usage, password strength, a 4.2-out-of-5 rating, API quota consumed, tickets closed out of an unchanging total that is not a task you are performing: **meter**. The frequent mistake is using `<meter>` for a loading bar because the colour bands look nice, or using `<progress>` for a static gauge because it is the more familiar element. Both mislead assistive technology, which announces them from different roles: a progress element is exposed as a progress indicator, a meter as a gauge. ## Both need a name Neither element names itself, and a bar announced only as "82%" tells a screen-reader user nothing. Both are *labelable*, which means a `<label for>` attaches to them exactly as it does to an input, and `aria-label` is an alternative when no visible text exists. Give every one of them a name. Also note that these are output-only. Neither is a control the user can operate, neither submits anything, and neither is a substitute for `<input type="range">` when you want the user to *choose* a value. ## The third display element: output Alongside these sits `<output>`, which represents the result of a calculation — a computed total, a converted unit, a live sum of the fields above it. Its `for` attribute takes a space-separated list of the ids of the elements that contributed to the result, and its value is simply its text content, which script updates. ```html <output name="total" for="qty price">0.00</output> ``` It is form-associated and it resets with the form, but it is not submitted — it is a derived value, and derived values belong to the server's own arithmetic, not to the request. Its default role is a status role, which is why calculated results placed in an `<output>` tend to be announced when they change, whereas the same number dropped into a `<span>` changes silently.
- How do you show a progress bar when you cannot estimate how long the task will take?Omit the `value` attribute. A `<progress>` with no value is in the indeterminate state and browsers render the animated "working" bar, which correctly communicates "started, duration unknown" rather than a fabricated percentage. Once you can compute a fraction, set `value` and the same element switches to a determinate bar — no swapping of elements and no separate spinner component.
- What do the low, high and optimum attributes on a meter actually do?They describe the scale rather than the value. `low` and `high` divide the range into three bands, and `optimum` says which end is good — it can sit in the low band, the middle, or the high band. From those the browser decides whether the current value is in the preferred, suboptimum or worst region and colours the gauge accordingly, so a reading of 0.9 can be good for a battery and alarming for disk usage.
- Why put a calculated total in an <output> element rather than a <span>?`<output>` says the content is the result of a calculation, and its `for` attribute names the ids of the fields that fed it, which documents the relationship in the markup. It is form-associated and resets with the form, though it is never submitted. Its default status role also means updates tend to be announced, so a screen-reader user hears the new total, while the same number in a `<span>` changes in silence.
saying these in an interview costs you the question
- Using meter for a loading or upload bar
- Using progress for a static gauge like disk usage
- Thinking the text inside progress is its label
- Expecting a meter or progress value to be submitted
- Treating meter as an input the user can drag