( Perceivable / WCAG 1.1.1 )

ARIA meter has no accessible name

SeriousLevel AWCAG 1.1.1 — Non-text Content

What is this issue?

An element carrying role="meter" has no accessible name: the text a screen reader announces to identify an element. It comes from the first source that applies, in order: aria-labelledby, aria-label, visible label text, then other fallbacks specific to the element type.

The meter role represents a scalar value within a known range (disk space used, a battery level, a five-star rating) and exposes that value through aria-valuenow, aria-valuemin, and aria-valuemax. Without an accessible name, the screen reader announces the numeric value and the role, but never says what the number represents.

Why does this matter?

A number on its own carries no meaning. “72 percent” could be storage used, battery remaining, a course completion score, or a product rating out of five converted to a percentage; a screen reader user has no way to distinguish between them without a name attached to the meter.

This matters most on dashboards and settings panels, where several meters often sit near each other: storage, bandwidth, and quota usage stacked in a row, for example. A sighted user tells them apart by reading the visible caption above each gauge. A screen reader user who only gets “72 percent, meter” repeated three times in a row has no way to know which number belongs to which resource.

Who is affected?

  • Screen reader users: hear a raw number with a role attached and no indication of what it measures, making the value functionally useless without exploring the surrounding page for a caption that may not even be programmatically connected.
  • Cognitive disabilities: users who rely on a screen reader to reduce reading load lose the immediate context a named meter provides, forcing extra navigation to confirm what a number means before it’s useful.

What users experience

Tobias uses VoiceOver on his Mac to check his cloud storage plan after getting a “storage almost full” email notification. The account page shows three meters (storage, shared links, and backup) stacked vertically, each built as <div role="meter"> with no aria-label. VoiceOver announces “91 percent, level 5 out of 6” for the first one with no name, and Tobias has no way to confirm it’s the storage meter and not one of the other two before deciding whether to delete files.

How do I fix it?

Add aria-label describing what the meter measures, such as aria-label="Storage used". This works because aria-label supplies the missing name directly, and meters are usually compact visual elements (a gauge or bar with a number) that don’t always have room for extra visible text a labelling attribute could reuse.

When a visible caption already sits next to the meter, such as a heading or text label in a dashboard card, use aria-labelledby pointing at that element’s id instead. This keeps a single source of truth for the meter’s name instead of a caption and an aria-label that could say two different things.

aria-valuetext is a separate, optional addition worth pairing with the name; it replaces the raw number with a more readable string like "91% used, 9.1 GB of 10 GB", but it doesn’t substitute for the accessible name and shouldn’t be added instead of aria-label.

Code Examples

Before
<div role="meter" aria-valuenow="72" aria-valuemin="0" aria-valuemax="100"></div>
After
<!-- Method 1: aria-label (compact widget, no visible caption to reuse) -->
<div
  role="meter"
  aria-label="Storage used"
  aria-valuenow="72"
  aria-valuemin="0"
  aria-valuemax="100"
></div>

<!-- Method 2: aria-labelledby (a visible caption already exists) -->
<h3 id="storage-caption">Storage used</h3>
<div
  role="meter"
  aria-labelledby="storage-caption"
  aria-valuenow="72"
  aria-valuemin="0"
  aria-valuemax="100"
  aria-valuetext="72% used, 7.2 GB of 10 GB"
></div>

Both methods give the meter a name that describes what’s being measured, so “72 percent” becomes “Storage used, 72 percent” for a screen reader. Method 2 also adds aria-valuetext, which replaces the bare percentage with a more concrete description, useful once the meter has a name and there’s a friendlier way to phrase the value itself.

Common Mistakes

Mistake: “The meter sits right under a heading that says ‘Storage,’ so it’s labelled.” Visual proximity does nothing for the accessible name computation unless the heading is connected with aria-labelledby pointing at its id. A screen reader reads the DOM’s programmatic relationships, not the visual layout, so an unconnected heading contributes nothing to the meter’s name.

Mistake: “aria-valuetext gives the meter enough context on its own.” aria-valuetext only changes how the value is announced; it never supplies the accessible name. A meter with aria-valuetext="72% used" but no aria-label still announces as an unnamed meter with a friendlier-sounding but still context-free number.

Mistake: “It’s a decorative gauge, so it doesn’t need an accessible name.” If a meter is purely decorative and conveys no information not available elsewhere in text, the correct fix is to hide it from assistive technology entirely with aria-hidden="true", not to leave it exposed with no name. A meter with role="meter" and no aria-hidden is announced as an interactive data point, so it needs a real name unless it’s explicitly hidden.

How RedFlag Detects This

Automated: axe-core rule, runs on every scan. RedFlag calls axe-core’s aria-meter-name rule as part of every scan, restricted to the WCAG 2.0/2.1/2.2 A and AA rule set. The rule selects every element with role="meter" and checks whether the accessible name computation resolves to non-empty text.

False negative: axe-core confirms a name exists but can’t judge whether it’s accurate. A meter labelled aria-label="Value" or aria-label="Meter" passes the automated check even though it tells the user nothing more than the role already does. False positive: none typical for this check, since resolving to a non-empty accessible name is a binary condition. Manual step: read the announced name and confirm it actually names what the meter measures, not a generic placeholder.

Manual Testing

  1. Open the page in Chrome or Firefox with NVDA or JAWS running.
  2. Navigate to each meter element on the page, commonly a storage gauge, a rating display, or a usage indicator.
  3. Listen to what’s announced. It should be a specific measurement (“Storage used, 91 percent”), not a bare value (“91 percent, meter”) with no context.
  4. If several meters appear near each other, confirm each one announces a distinct, correct name rather than all sharing the same generic label.
  5. Repeat with VoiceOver on a Mac to confirm the announcement is consistent, since meter support varies slightly by screen reader and browser combination.

1.1.1 Non-text Content: Non-text content must have a text alternative that serves the equivalent purpose. A meter’s visual gauge conveys a measurement graphically; its accessible name and value together are the text alternative for that graphic, and a missing name breaks the equivalence this criterion requires.

4.1.2 Name, Role, Value: Every interface component must expose a name, role, and current value to assistive technology. A meter with no accessible name has a role and a value from aria-valuenow, but no name, which is this criterion’s requirement failing at the same time as 1.1.1.

ARIA progressbar has no accessible name is the closest sibling to this rule: the identical missing-name problem on the role for operations moving toward completion, rather than a static or slowly-changing gauge.

ARIA command has no accessible name covers the same underlying naming failure applied to interactive controls instead of a read-only data display like a meter.

ARIA input field has no accessible name shares the same fix pattern, aria-label or aria-labelledby, applied to data-entry widgets rather than value displays.

ARIA attribute is required but missing is worth checking on the same element, since a meter role also requires aria-valuenow, aria-valuemin, and aria-valuemax to be fully valid, independent of whether it has a name.

References

Frequently asked questions

What is the difference between a meter and a progressbar role?

A meter represents a value within a known, fixed range that is not necessarily moving toward completion, such as disk usage or a star rating. A progressbar represents an operation moving toward completion over time, such as a file upload. Both need an accessible name for the same reason, but they are semantically distinct roles.

Does aria-valuetext replace the need for aria-label on a meter?

No. aria-valuetext changes what is announced for the current value, for example replacing "72" with "72 percent full," but it does not supply the meter with a name describing what is being measured. A meter needs both an accessible name and, optionally, a more readable value string.

Can a meter share a label with a visible number displayed next to it?

Yes, using aria-labelledby pointing at the id of the visible caption. This is usually the best option for a meter, since dashboards and settings panels almost always render a text caption next to the visual gauge already.

Does this rule apply to a native HTML meter element?

The native meter element resolves its accessible name the same way ARIA meter role elements do, through a label, aria-label, or aria-labelledby, so the identical naming rule applies. Most implementations of this failure use a div with role="meter" rather than the native element, since native meter has limited styling flexibility.

Is a percentage sign enough context for the meter value?

No. A bare percentage tells a screen reader user a number is between 0 and 100 but not what it is measuring: storage, battery, a rating, progress toward a goal. The accessible name is what supplies that missing context, not the value or its unit.