View non-AMP version at deque.com

Ambiguous IDs: Harmless Lurker or Queen of Disaster?

A Little Background

Duplicate IDs of the most common WCAG 4.1.1 violations reported by automated accessibility testing tools such as axe, and it can cause a fair share of problems for your users. It happens when more than one element on the webpage have the same ID attribute. People often ask me how these seemingly innocuous ambiguous IDs can cause so many problems.

The simple answer: as with so many accessibility and usability issues, it really depends on the situation and how ID attributes are used. Sometimes, the use of non-unique ID attributes can be disastrous – and not just for accessibility, but for usability too. I’ll show you how in this example.

Example 1 – Dude, which credit card did I use?

The following situation did not occur A long long time ago, in a galaxy far far away. It happened on a real webpage of a real corporation.

Which credit card do you wish to use to pay this invoice?



With your mouse, try clicking on the second or third label in the form (“Card ending in 9892” or “Card ending in 2388”):

Q: Which checkbox got checked?

A: Most likely the first checkbox (“Card ending in 4499”).

Hold on. What happened?

On this form the labels are explicitly associated with their checkboxes (the value of the label’s attribute matches the ID of the checkbox). When done right, this translates into being both accessible and easy-to-use. When a label is specifically associated with a form field, users can click on the label with the mouse to interact with the form field. For example, they can check or uncheck a checkbox or radiobutton or move focus into a text input field. The enlarged clickable area benefits a lot of users, like older people with low vision, or people with limited fine motor control. It’s also helpful for your regular old Joe (or Joanna), simply because it’s easier to see and use.

But in our example all the checkboxes had the same ID. This is invalid HTML and the browser must do its best to compensate. Most browsers look for the first element in the DOM whose ID matches the one specified in the label element’s “for” attribute. Then the label is associated with that element.

And so it came to pass that all 3 labels got associated with the first checkbox. The other checkboxes were left out in the cold, empty and nameless.

But when I click directly on the checkbox or check it with the space bar, everything is fine!

When you interact with the control directly, the browser doesn’t have to guess which checkbox you needed.

I see this is a usability problem. But why is this an accessibility problem?

People often say that accessibility is usability on steroids. And here’s why:

Users of assistive technology applications such as screen readers rely on programmatic associations to a much larger extent than regular users. They can’t see the screen, so visual placement, proximity, and cues don’t do much for them.

When a screen reader user moves focus to a form field, the screen reader has to announce the field’s accessible name. The screen reader looks for the label associated with the form field and announces the label’s text contents as the form field’s accessible name.

In my example the screen reader is stumped. When the user moves focus to the first checkbox, It finds not 1 but 3 labels associated with it. Most screen readers link their text content into one string and announce that string as the checkbox’s accessible name.

I tested this example running NVDA 2023.1 and Jaws 2023 with Chrome 116.0.5845.97.

The first checkbox is announced like this: “Card ending in 4499 Card ending in 9892 Card ending in 2388 checkbox not checked” by both screen readers.

The situation gets even more confusing for checkboxes 2 and 3. JAWS and NVDA do not announce an accessible name for these checkboxes. The screen reader user has no reliable technique other than selecting a checkbox at random in the hopes that the information about the card will be revealed later in the process.

So how serious is this problem?

If your customer accidentally selects the wrong credit card to pay a bill, that means they’ll end up making a financial transaction they didn’t intend to make, which could end up hurting customer relationships.

Of course, you can partially address the potential problem by complying with WCAG success criterion 3.3.4 which would give the customer a chance to confirm or correct his data. But ultimately it would be better to prevent this kind of mishap from happening in the first place.

Example 2 – screen readers talking rot.

Sometimes accessibility requires developers to programmatically expose a relationship between page elements on a webpage to assistive technologies. A common scenario is when instructions are associated with a form field. Visually this is achieved by placing the element with instructional text close to the form field on the screen, or by displaying the instructional content as a tooltip when the user mouses over or puts focus on the form field. But screen readers aren’t able to communicate that info without additional markup.

No need to worry! We can easily provide the required mark up using the aria-describedby attribute. The attribute goes on the form field and its value is the ID (or a space separated list of IDs) of the element or elements that screen readers should announce when user puts focus on the form field.

And so we find ourselves back to ID attributes. What should the screen reader do if the value of the aria-describedby attribute points to an ID used by more than one element?

Screen reader hints gone wrong.

You can only use letters and white space, no numbers please!
Use all numbers, no dashes, no letters, no nonsense.

Here I’ve provided helpful tooltips for both form fields in a way that screen reader users won’t understand.

  • The <span> elements containing the hints have the same ID attribute: id="hint".
  • Both form fields point to their hint elements using aria-describedby="hint".

This is invalid HTML though it will probably only affect users of assistive technologies.

How will the screen readers handle this mess?

Testing with the same combination as in the first example, I shifted my focus to the phone number input field. Guess what I heard?

  • JAWS: “Please enter your phone number, edit. You can only use letters and white space, no numbers please..
  • NVDA: “Please enter your phone number, edit. You can only use letters and white space, no numbers please..

Uh-oh. Both screen readers look for the first instance of the referenced ID and announce the text contents of that element.

And so it came to pass that all screen reader users in the land were told to enter their phone numbers using only letters or spaces.

So, how serious are non-unique IDs?

Let’s recap.

If the IDs are not used by attributes or scripting on your webpage, the chances are that they won’t affect the accessibility of your webpage. But the minute that an ID attribute is used to provide programmatic relationship on your webpage, it starts affecting your users.

There are many situations where IDs are used for providing functionality on webpages. I’ve only listed 2 of the most common ones.

Besides providing programmatic context as demonstrated here, ID attributes can be used as targets for Javascript or CSS selectors. Use your imagination to think of the myriad of scenarios that can arise when your selectors are not working the way you expected.

I used the case of a screen reader user to illustrate the problem, but many other assistive technologies, such as speech recognition software and screen magnifiers take advantage of programmatic relationships between webpage elements. As assistive technology solutions make their way into the mainstream (such as in speech-enabled web browsing solutions for cars), it’s likely that the number of users relying on the uniqueness of your ID attributes is going to grow.

What should I do?

Remember: A webpage element has certain inalienable rights; having a unique ID is one of them.

Prevent html element identity theft by ensuring that every element on your webpage that needs an ID has a unique one.

This will save your users a lot of headaches and decrease the chances of confusing your customer service staff. It will also reduce the instances of developer frustration, and, in severe cases, damage to office furniture. 🙂

*Special shout out to Birkir Gunnarson for his previous contributions to this piece.

Exit mobile version