aria-valuemax
Defines the maximum allowed value for a range widget. Used with sliders, progress bars, spinbuttons, and meters to establish the upper bound of the value range.
Overview
The aria-valuemax attribute defines the maximum value allowed for a range widget. It works together with aria-valuemin and aria-valuenow to define the complete range.
For progress indicators, this defines the "complete" state. When aria-valuenow equals aria-valuemax, the task is 100% complete.
Indeterminate Progress
For loading states where the total is unknown, omit all three value attributes. This creates an indeterminate progress bar that screen readers announce as "busy" or "loading".
Live Demo: Progress Bar
Current ARIA attributes:
aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"Screen reader: "File Upload Progress, progress bar, 0%". At 100%: "File Upload Progress, progress bar, 100%, complete".
Code Examples
Basic Usage
<!-- Basic aria-valuemax usage -->
<!-- Slider with max value of 100 -->
<div
role="slider"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="75"
aria-label="Volume"
tabindex="0"
>
75%
</div>
<!-- Progress bar with custom max -->
<div
role="progressbar"
aria-valuemin="0"
aria-valuemax="500"
aria-valuenow="350"
aria-label="File upload"
aria-valuetext="350 of 500 MB uploaded"
>
350 MB / 500 MB
</div>
<!-- Spinbutton with max limit -->
<div
role="spinbutton"
aria-valuemin="0"
aria-valuemax="99"
aria-valuenow="25"
aria-label="Quantity"
tabindex="0"
>
25
</div>Custom Max Values
<!-- Different max value scenarios -->
<!-- 5-star rating -->
<div
role="slider"
aria-valuemin="0"
aria-valuemax="5"
aria-valuenow="4"
aria-label="Rating"
aria-valuetext="4 out of 5 stars"
tabindex="0"
>
★★★★☆
</div>
<!-- Percentage progress (common: max=100) -->
<div
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="65"
aria-label="Course completion"
>
65% complete
</div>
<!-- File count progress -->
<div
role="progressbar"
aria-valuemin="0"
aria-valuemax="150"
aria-valuenow="87"
aria-label="Files processed"
aria-valuetext="87 of 150 files"
>
87 / 150 files
</div>
<!-- Step progress -->
<div
role="progressbar"
aria-valuemin="1"
aria-valuemax="5"
aria-valuenow="3"
aria-label="Checkout progress"
aria-valuetext="Step 3 of 5: Shipping"
>
Step 3 of 5
</div>Indeterminate Progress
<!-- Indeterminate progress (unknown max) -->
<!-- Loading spinner (no specific max) -->
<div
role="progressbar"
aria-label="Loading..."
>
<!-- No aria-valuemin, aria-valuemax, or aria-valuenow -->
<!-- This indicates indeterminate progress -->
Loading...
</div>
<!-- Screen reader: "Loading..., progress bar, busy" -->
<!-- Alternative: Use aria-busy -->
<div
role="region"
aria-busy="true"
aria-label="Content loading"
>
<div role="progressbar" aria-label="Loading">
<!-- Spinner animation -->
</div>
</div>
<!-- Once complete, add values -->
<div
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="100"
aria-label="Loading complete"
>
Complete!
</div>React Components
// React Progress Bar with aria-valuemax
import { useState, useEffect } from 'react';
function ProgressBar({
value,
max = 100,
min = 0,
label,
showPercentage = true,
indeterminate = false,
}) {
const percentage = indeterminate
? null
: Math.round(((value - min) / (max - min)) * 100);
return (
<div className="progress-container">
<label id="progress-label">{label}</label>
<div
role="progressbar"
aria-labelledby="progress-label"
{...(indeterminate ? {} : {
'aria-valuemin': min,
'aria-valuemax': max,
'aria-valuenow': value,
})}
className={`progress-bar ${indeterminate ? 'indeterminate' : ''}`}
>
<div
className="progress-fill"
style={{
width: indeterminate ? '30%' : `${percentage}%`,
animation: indeterminate ? 'indeterminate 1.5s infinite' : 'none'
}}
/>
</div>
{!indeterminate && showPercentage && (
<span className="progress-text">{percentage}%</span>
)}
</div>
);
}
// File Upload Progress
function FileUploadProgress({
uploadedBytes,
totalBytes,
fileName
}) {
const percentage = Math.round((uploadedBytes / totalBytes) * 100);
const uploadedMB = (uploadedBytes / 1024 / 1024).toFixed(1);
const totalMB = (totalBytes / 1024 / 1024).toFixed(1);
return (
<div className="upload-progress">
<span className="file-name">{fileName}</span>
<div
role="progressbar"
aria-valuemin={0}
aria-valuemax={totalBytes}
aria-valuenow={uploadedBytes}
aria-label={`Uploading ${fileName}`}
aria-valuetext={`${uploadedMB} of ${totalMB} MB uploaded`}
className="progress-bar"
>
<div
className="progress-fill"
style={{ width: `${percentage}%` }}
/>
</div>
<span className="progress-stats">
{uploadedMB} MB / {totalMB} MB ({percentage}%)
</span>
</div>
);
}
// Multi-step Progress
function StepProgress({ currentStep, totalSteps, stepLabels }) {
return (
<div className="step-progress">
<div
role="progressbar"
aria-valuemin={1}
aria-valuemax={totalSteps}
aria-valuenow={currentStep}
aria-label="Checkout progress"
aria-valuetext={`Step ${currentStep} of ${totalSteps}: ${stepLabels[currentStep - 1]}`}
className="steps-container"
>
{stepLabels.map((label, index) => (
<div
key={label}
className={`step ${index + 1 <= currentStep ? 'completed' : ''}`}
>
<div className="step-number">{index + 1}</div>
<span className="step-label">{label}</span>
</div>
))}
</div>
</div>
);
}
// Usage
function App() {
const [progress, setProgress] = useState(0);
return (
<>
<ProgressBar
value={progress}
max={100}
label="Download Progress"
/>
<FileUploadProgress
uploadedBytes={350 * 1024 * 1024}
totalBytes={500 * 1024 * 1024}
fileName="video.mp4"
/>
<StepProgress
currentStep={3}
totalSteps={5}
stepLabels={['Cart', 'Shipping', 'Payment', 'Review', 'Confirm']}
/>
</>
);
}Best Practices
Set aria-valuemax higher than aria-valuemin to define a valid range
Use meaningful max values (e.g., file size in bytes, total steps)
Omit all value attributes for indeterminate/unknown progress
Consider using aria-valuetext for human-readable descriptions
Update valuenow dynamically as progress changes
Don't set aria-valuenow higher than aria-valuemax
Don't use on native HTML progress/meter elements—they have max attribute
Don't forget to pair with aria-valuemin and aria-valuenow

