aria-valuemin
Defines the minimum allowed value for a range widget. Used with sliders, progress bars, spinbuttons, and meters to establish the lower bound of the value range.
Overview
The aria-valuemin attribute defines the minimum value allowed for a range widget. It works together with aria-valuemax and aria-valuenow to define the complete range and current value.
This attribute is required for custom range widgets using roles like slider, progressbar, spinbutton, scrollbar, and meter.
Native Elements
For native HTML elements like <input type="range">, use the min attribute instead. The browser handles accessibility automatically.
Live Demo: Custom Slider
Current ARIA attributes:
aria-valuemin="0" aria-valuemax="100" aria-valuenow="50"Screen reader: "Volume Control, slider, 50%, minimum 0, maximum 100". Use arrow keys to adjust, Home for minimum, End for maximum.
Supported Roles
sliderRange selection control
progressbarTask completion indicator
spinbuttonNumeric input with buttons
scrollbarScroll position indicator
meterGauge/measurement display
separatorWhen focusable/adjustable
Code Examples
Basic Usage
<!-- Basic aria-valuemin usage -->
<!-- Slider with minimum value -->
<div
role="slider"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="50"
aria-label="Volume"
tabindex="0"
>
50%
</div>
<!-- Screen reader: "Volume, slider, 50%, minimum 0, maximum 100" -->
<!-- Progress bar -->
<div
role="progressbar"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="75"
aria-label="Download progress"
>
75% complete
</div>
<!-- Spinbutton with min value -->
<div
role="spinbutton"
aria-valuemin="1"
aria-valuemax="10"
aria-valuenow="5"
aria-label="Quantity"
tabindex="0"
>
5
</div>Different Minimum Values
<!-- Range slider with different min values -->
<!-- Temperature slider (negative min) -->
<div
role="slider"
aria-valuemin="-20"
aria-valuemax="40"
aria-valuenow="22"
aria-label="Temperature"
aria-valuetext="22 degrees Celsius"
tabindex="0"
>
22°C
</div>
<!-- Price range (decimal min) -->
<div
role="slider"
aria-valuemin="0.01"
aria-valuemax="1000.00"
aria-valuenow="29.99"
aria-label="Price"
aria-valuetext="$29.99"
tabindex="0"
>
$29.99
</div>
<!-- Year selector -->
<div
role="slider"
aria-valuemin="1900"
aria-valuemax="2024"
aria-valuenow="1990"
aria-label="Birth year"
tabindex="0"
>
1990
</div>Meter Examples
<!-- Meter with custom min/max -->
<div
role="meter"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="85"
aria-label="Battery level"
>
85%
</div>
<!-- Storage meter (in GB) -->
<div
role="meter"
aria-valuemin="0"
aria-valuemax="512"
aria-valuenow="340"
aria-label="Storage used"
aria-valuetext="340 GB of 512 GB used"
>
340 GB / 512 GB
</div>
<!-- Score meter with non-zero min -->
<div
role="meter"
aria-valuemin="100"
aria-valuemax="800"
aria-valuenow="720"
aria-label="Credit score"
>
720 (Excellent)
</div>Native HTML Elements
<!-- Native HTML elements (automatic min support) -->
<!-- HTML5 range input - use min attribute -->
<input
type="range"
min="0"
max="100"
value="50"
aria-label="Brightness"
/>
<!-- Native inputs DON'T need aria-valuemin -->
<!-- The 'min' attribute handles it automatically -->
<!-- HTML5 number input -->
<input
type="number"
min="1"
max="100"
value="10"
aria-label="Quantity"
/>
<!-- HTML5 progress element -->
<progress max="100" value="75">75%</progress>
<!-- Progress starts from 0 by default -->
<!-- HTML5 meter element -->
<meter min="0" max="100" value="75">75%</meter>React Component
// React Custom Slider with aria-valuemin
import { useState, useCallback, useRef } from 'react';
function CustomSlider({
min = 0,
max = 100,
value,
onChange,
label,
valueText,
step = 1,
}) {
const sliderRef = useRef(null);
// Calculate percentage for visual display
const percentage = ((value - min) / (max - min)) * 100;
const handleKeyDown = useCallback((e) => {
let newValue = value;
switch (e.key) {
case 'ArrowRight':
case 'ArrowUp':
newValue = Math.min(value + step, max);
break;
case 'ArrowLeft':
case 'ArrowDown':
newValue = Math.max(value - step, min);
break;
case 'Home':
newValue = min;
break;
case 'End':
newValue = max;
break;
case 'PageUp':
newValue = Math.min(value + step * 10, max);
break;
case 'PageDown':
newValue = Math.max(value - step * 10, min);
break;
default:
return;
}
e.preventDefault();
onChange?.(newValue);
}, [value, min, max, step, onChange]);
return (
<div className="slider-container">
<label id="slider-label">{label}</label>
<div
ref={sliderRef}
role="slider"
aria-valuemin={min}
aria-valuemax={max}
aria-valuenow={value}
aria-valuetext={valueText || String(value)}
aria-labelledby="slider-label"
tabIndex={0}
onKeyDown={handleKeyDown}
className="slider-track"
>
<div
className="slider-fill"
style={{ width: `${percentage}%` }}
/>
<div
className="slider-thumb"
style={{ left: `${percentage}%` }}
/>
</div>
<div className="slider-labels">
<span>{min}</span>
<span>{value}</span>
<span>{max}</span>
</div>
</div>
);
}
// Usage examples
function VolumeControl() {
const [volume, setVolume] = useState(50);
return (
<CustomSlider
label="Volume"
min={0}
max={100}
value={volume}
onChange={setVolume}
valueText={`${volume}%`}
/>
);
}
function TemperatureControl() {
const [temp, setTemp] = useState(22);
return (
<CustomSlider
label="Temperature"
min={-10}
max={40}
value={temp}
onChange={setTemp}
valueText={`${temp}°C`}
step={0.5}
/>
);
}Best Practices
Always use with aria-valuemax and aria-valuenow for complete range context
Use numeric values that make sense for the context (can be negative or decimal)
Consider adding aria-valuetext for human-readable value descriptions
Implement keyboard support: Arrow keys, Home (min), End (max)
Prevent aria-valuenow from going below aria-valuemin
Don't use on native HTML range inputs—they have their own min attribute
Don't set aria-valuemin higher than aria-valuemax
Don't forget to update valuenow when user interacts

