Loading Developer Playground

Loading ...

Skip to main content
ARIA ATTRIBUTEWidget Attributes

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.

Value Type
number
Common Use
Range Widgets
Used With
valuemax, valuenow

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

0 (min)50%100 (max)

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

slider

Range selection control

progressbar

Task completion indicator

spinbutton

Numeric input with buttons

scrollbar

Scroll position indicator

meter

Gauge/measurement display

separator

When 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

Related Attributes

Specifications & Resources