The HTML aria-valuemax attribute
The aria-valuemax attribute sets the maximum value of a custom range widget, such as role="slider" or role="progressbar". Most range roles default to 100 without it, so set it whenever your range ends elsewhere. Native <progress> and range inputs use max instead.
Overview
The aria-valuemax attribute defines the highest value a custom range widget can reach. Paired with aria-valuemin and aria-valuenow, it tells assistive technology how big the range is and how far along the current value is. WAI-ARIA requires it to be greater than or equal to aria-valuemin.
A slider, scrollbar, progress bar, meter or focusable separator with no aria-valuemax is treated as having a maximum of 100. That default is easy to trip over. A rating slider that stops at 5 but leaves out aria-valuemax describes a value of 4 against a range that ends at 100, as our Chrome accessibility tree test showed.
A spinbutton works the other way. It has no maximum unless you set one, so leave aria-valuemax off only when the number really has no upper limit, such as a quantity field with no cap.
The WAI-ARIA Authoring Practices slider pattern maps the End key to the last allowed value, so a keyboard handler should use the same number as aria-valuemax. On native <input type="range">, <meter> and <progress> elements, skip it and use the HTML max attribute, as ARIA in HTML recommends.
Syntax
<div role="progressbar" aria-label="Upload" aria-valuemin="0" aria-valuemax="250" aria-valuenow="125"></div>
Values
| Value |
|---|
| A number. |
Example
<p><span id="rating-label">Rating</span> (focus the box, then use the arrow keys, Home or End)</p>
<div id="rating" style="display: inline-block; padding: 6px 10px; border: 1px solid #767676;" role="slider" tabindex="0" aria-labelledby="rating-label" aria-valuemin="1" aria-valuemax="5" aria-valuenow="3" aria-valuetext="3 of 5 stars">3 of 5</div>
<script>
const r = document.getElementById('rating');
r.addEventListener('keydown', function (e) {
const min = Number(r.getAttribute('aria-valuemin'));
const max = Number(r.getAttribute('aria-valuemax'));
let v = Number(r.getAttribute('aria-valuenow'));
if (e.key === 'ArrowRight' || e.key === 'ArrowUp') v = Math.min(max, v + 1);
else if (e.key === 'ArrowLeft' || e.key === 'ArrowDown') v = Math.max(min, v - 1);
else if (e.key === 'Home') v = min;
else if (e.key === 'End') v = max;
else return;
e.preventDefault();
r.setAttribute('aria-valuenow', v);
r.setAttribute('aria-valuetext', v + ' of ' + max + ' stars');
r.textContent = v + ' of ' + max;
});
</script>
Best practices
- Set
aria-valuemaxwhenever the range doesn't end at 100, since most range roles assume 100. - Keep
aria-valuemaxand the End key in sync, so End jumps to the value assistive technology reports as the maximum. - Add aria-valuetext when the raw number needs context, such as 3 of 5 stars.
- Update
aria-valuemaxwhen the total changes, for example when more files join an upload queue. - Use the native
maxattribute on<progress>,<meter>and range inputs instead ofaria-valuemax.
Frequently asked questions
What does aria-valuemax do?
What maximum does a range widget use without aria-valuemax?
Why does my custom progress bar announce the wrong percentage?
Do I need aria-valuemax on a progress element?
input type=range elements.






















