Loading Developer Playground

Loading ...

Skip to main content
ARIA ATTRIBUTEWidget Attributes

aria-valuetext

Defines the human-readable text alternative of aria-valuenow for a range widget. Provides meaningful context when the numeric value alone isn't sufficient.

Value Type
string
Common Use
Human-Readable Values
Used With
aria-valuenow

Overview

The aria-valuetext attribute provides a human-readable text alternative to the numeric aria-valuenow value. When present, screen readers announce the valuetext instead of the raw number.

This is essential when the numeric value isn't meaningful on its own—like star ratings ("4 out of 5 stars"), temperatures with descriptions, time values, or progress states.

When to Use

Use aria-valuetext when the numeric value needs context: star ratings, temperature feelings, time formats, progress phases, or any value that benefits from description.

Live Demo

22°C - Comfortable

4 stars - Very Good

Screen reader: Temperature: "22°C - Comfortable". Rating: "4 stars - Very Good". The valuetext provides meaningful context instead of just numbers.

Code Examples

Basic Usage

<!-- aria-valuetext provides human-readable value -->

<!-- Temperature slider with descriptive text -->
<div
  role="slider"
  aria-valuemin="0"
  aria-valuemax="40"
  aria-valuenow="22"
  aria-valuetext="22 degrees Celsius, Comfortable"
  aria-label="Room temperature"
  tabindex="0"
>
  22°C
</div>
<!-- Screen reader: "Room temperature, slider, 22 degrees Celsius, Comfortable" -->
<!-- Without valuetext: "Room temperature, slider, 22" (less meaningful) -->

<!-- Star rating with descriptive text -->
<div
  role="slider"
  aria-valuemin="0"
  aria-valuemax="5"
  aria-valuenow="4"
  aria-valuetext="4 out of 5 stars, Very Good"
  aria-label="Product rating"
  tabindex="0"
>
  ★★★★☆
</div>

Contextual Descriptions

<!-- Contextual value descriptions -->

<!-- Time slider -->
<div
  role="slider"
  aria-valuemin="0"
  aria-valuemax="1440"
  aria-valuenow="810"
  aria-valuetext="1:30 PM"
  aria-label="Meeting time"
  tabindex="0"
>
  1:30 PM
</div>

<!-- Progress with descriptive phases -->
<div
  role="progressbar"
  aria-valuemin="0"
  aria-valuemax="100"
  aria-valuenow="65"
  aria-valuetext="65%, Processing images"
  aria-label="Upload progress"
>
  65% - Processing images...
</div>

<!-- Price range -->
<div
  role="slider"
  aria-valuemin="0"
  aria-valuemax="1000"
  aria-valuenow="299"
  aria-valuetext="$299, Mid-range"
  aria-label="Price filter"
  tabindex="0"
>
  $299
</div>

<!-- Date selection -->
<div
  role="slider"
  aria-valuemin="1"
  aria-valuemax="365"
  aria-valuenow="45"
  aria-valuetext="February 14th, Valentine's Day"
  aria-label="Date selector"
  tabindex="0"
>
  Feb 14
</div>

React Components

// React components with aria-valuetext
import { useState, useMemo } from 'react';

// Temperature Slider with descriptive text
function TemperatureSlider({ value, onChange, min = 0, max = 40 }) {
  const valueText = useMemo(() => {
    if (value < 10) return `${value}°C - Cold`;
    if (value < 18) return `${value}°C - Cool`;
    if (value < 24) return `${value}°C - Comfortable`;
    if (value < 30) return `${value}°C - Warm`;
    return `${value}°C - Hot`;
  }, [value]);
  
  return (
    <div className="temperature-slider">
      <label id="temp-label">Room Temperature</label>
      <div
        role="slider"
        aria-labelledby="temp-label"
        aria-valuemin={min}
        aria-valuemax={max}
        aria-valuenow={value}
        aria-valuetext={valueText}
        tabIndex={0}
        onKeyDown={(e) => {
          if (e.key === 'ArrowRight') onChange(Math.min(value + 1, max));
          if (e.key === 'ArrowLeft') onChange(Math.max(value - 1, min));
        }}
      >
        <div className="slider-track">
          <div 
            className="slider-fill" 
            style={{ width: `${((value - min) / (max - min)) * 100}%` }}
          />
        </div>
        <span className="value-display">{valueText}</span>
      </div>
    </div>
  );
}

// Star Rating with descriptive text
function StarRating({ value, onChange, max = 5 }) {
  const ratingTexts = [
    'No rating',
    '1 star - Poor',
    '2 stars - Fair', 
    '3 stars - Good',
    '4 stars - Very Good',
    '5 stars - Excellent'
  ];
  
  return (
    <div className="star-rating">
      <label id="rating-label">Your Rating</label>
      <div
        role="slider"
        aria-labelledby="rating-label"
        aria-valuemin={0}
        aria-valuemax={max}
        aria-valuenow={value}
        aria-valuetext={ratingTexts[value]}
        tabIndex={0}
        onKeyDown={(e) => {
          if (e.key === 'ArrowRight') onChange(Math.min(value + 1, max));
          if (e.key === 'ArrowLeft') onChange(Math.max(value - 1, 0));
        }}
      >
        {[1, 2, 3, 4, 5].map(star => (
          <button
            key={star}
            onClick={() => onChange(star)}
            className={star <= value ? 'filled' : 'empty'}
            aria-label={`Rate ${star} stars`}
          >
            {star <= value ? '★' : '☆'}
          </button>
        ))}
      </div>
      <span className="rating-text">{ratingTexts[value]}</span>
    </div>
  );
}

// Time Picker with formatted time
function TimePicker({ minutes, onChange }) {
  const formatTime = (mins) => {
    const hours = Math.floor(mins / 60);
    const m = mins % 60;
    const period = hours >= 12 ? 'PM' : 'AM';
    const displayHours = hours % 12 || 12;
    return `${displayHours}:${m.toString().padStart(2, '0')} ${period}`;
  };
  
  return (
    <div
      role="slider"
      aria-label="Select time"
      aria-valuemin={0}
      aria-valuemax={1440}
      aria-valuenow={minutes}
      aria-valuetext={formatTime(minutes)}
      tabIndex={0}
    >
      {formatTime(minutes)}
    </div>
  );
}

Related Attributes

Specifications & Resources