Max Design

Published:

A quick explanation of aria-valuenow - looking at native and non-native controls.

1. Native control

Let's start with a normal HTML range input. This will help us understand what aria-valuenow is trying to achieve.

A range input is a UI control that allows users to move a handle along a bar to choose a value. It is commonly known as a slider.

It looks something like this, depending on the browser:

A simple range slider showing a volume label and the slider set to 40

And the markup might look like this:

<label for="volume-select">Volume</label>

<input
  type="range"
  id="volume-select"
  min="0"
  max="100"
  value="40"
>

A native control like this comes with a lot of information and behaviour already built in.

The browser knows its name:

“Volume”

It knows its role:

“This is a slider.”

It knows the lowest possible value:

0

It knows the highest possible value:

100

And most importantly for this article, it knows the current value:

40

If the user moves the slider, the browser updates that value automatically.

For example, if the user presses the right arrow key and moves the slider from 40 to 41, the browser knows that the current value is now 41.

It can also pass that information to assistive technology, so a screen reader can announce the changing value as the user interacts with the control.

That is one of the big advantages of using a native HTML control: the browser already understands what the control is, how it behaves, and what its current value is.

2. Non-native control

Sometimes a native range input does not provide enough control over how the slider needs to look or behave.

For example:

In these situations, a developer may choose to build their own slider using generic HTML elements, then add the necessary styles with CSS and behaviour with JavaScript.

The markup might start out looking something like this:

<div>Volume</div>

<div>
  <div></div>
</div>

Visually, it could be styled to look almost exactly like a slider.

But the browser does not automatically know:

The developer now has to recreate those things.

3. Rebuilding the missing information

Let's start adding the information and behaviour that the native range input gave us automatically.

First, we need to tell the browser what kind of control this is:

<div
  role="slider"
>
</div>

The role="slider" tells assistive technologies:

“This is a slider.”

Next, the slider needs an accessible name. We can use the visible “Volume” text as its label:

<span id="volume-label">Volume</span>

<div
  role="slider"
  aria-labelledby="volume-label"
>
</div>

Now the browser can understand both the control's name and role.

The slider also needs to be keyboard focusable. A normal <div> is not focusable by default, so we can add tabindex="0".

<div
  role="slider"
  aria-labelledby="volume-label"
  tabindex="0"
>
</div>

Next, we need to provide information about the slider's range. Our volume control goes from 0 to 100, so we can add:

<span id="volume-label">Volume</span>

<div
  role="slider"
  aria-labelledby="volume-label"
  tabindex="0"
  aria-valuemin="0"
  aria-valuemax="100"
>
</div>

The browser now knows:

But one important piece of information is still missing:

What is the slider's current value?

This is where aria-valuenow comes in.

4. So what does aria-valuenow do?

aria-valuenow tells assistive technology the current numeric value of a range control.

For our volume slider, the current value is 40:

<span id="volume-label">Volume</span>

<div
  role="slider"
  tabindex="0"
  aria-labelledby="volume-label"
  aria-valuemin="0"
  aria-valuemax="100"
  aria-valuenow="40"
>
</div>

The aria-valuenow="40" basically means:

“The current value of this slider is 40.”

Now the browser has the important information about the slider's range and current value:

If the user moves the slider, the visual position of the handle needs to change.

But because this is a custom slider, the developer also needs to update aria-valuenow at the same time.

For example, if the user presses the right arrow key and moves the slider from 40 to 41, JavaScript should change:

aria-valuenow="40"

to:

aria-valuenow="41"

That changing value is what tells assistive technology that the slider's current value has changed.

In the working example, the same JavaScript update keeps the visual slider position, the visible number and aria-valuenow in sync.

If a developer updates the visual slider position but forgets to also update aria-valuenow, the accessible value does not just go missing, it goes stale and wrong, silently telling screen reader users the value is still 40 long after it has actually moved to 75. That is a worse outcome than having no ARIA at all, since a confidently wrong value is harder to notice than an obviously missing one.

Takeaway

aria-valuenow does not move the slider or create the interaction. JavaScript provides the behaviour and updates the value.

aria-valuenow communicates the current numeric value of a range control to assistive technology.

Test page

Testing a native vs custom slider