The HTML aria-describedby attribute
The aria-describedby attribute links an element to the text that explains it, such as a form hint. Its value is one or more ids, and the text becomes the accessible description, alongside the name. That description is a flat string, so headings, lists and tables in it lose their structure.
Overview
The aria-describedby attribute builds an accessible description from other elements, listed by id. It's allowed on all elements, so it isn't limited to form controls.
A name says what an element is, and a description adds to that. The name is a short label, and the description a short explanation. A field can be named Username by its <label> and described by a hint reading Use 3 to 12 letters or digits.
The referenced content ends up as one flat string. A heading, a list and a table turn into a single line of text, with the structure gone. Extensive or structured content belongs in aria-details instead.
The AccName 1.2 Working Draft takes the first applicable source. It ranks aria-describedby, then aria-description, then HTML features such as a table's caption, then title. So a title doesn't reach the description of a named control that has this attribute.
A broken reference and an empty one behave differently. If an id matches nothing, Chrome and Firefox both move on to the next source. If it points at an empty element, Chrome stops, following that draft's rule "even if that markup results in an empty description", while Firefox moves on.
Syntax
<label for="user">Username</label>
<input id="user" aria-describedby="user-hint">
<p id="user-hint">Use 3 to 12 letters or digits.</p>
Values
| Value |
|---|
| A space-separated list of element id values. |
Example
<p>Press Check with the box empty, then with a valid name.</p>
<form id="signup" novalidate>
<label for="user">Username</label>
<input id="user" type="text" aria-describedby="user-hint" autocomplete="username">
<button type="submit">Check</button>
<p id="user-hint">Use 3 to 12 letters or digits.</p>
<p id="user-error" hidden>That username won't work.</p>
</form>
<p role="status" id="out">aria-describedby is user-hint</p>
<script>
const input = document.getElementById('user');
const error = document.getElementById('user-error');
const out = document.getElementById('out');
document.getElementById('signup').addEventListener('submit', function (event) {
event.preventDefault();
const valid = /^[a-z0-9]{3,12}$/i.test(input.value);
input.setAttribute('aria-describedby', valid ? 'user-hint' : 'user-error user-hint');
error.hidden = valid;
if (valid) input.removeAttribute('aria-invalid');
else input.setAttribute('aria-invalid', 'true');
out.textContent = 'aria-describedby is ' + input.getAttribute('aria-describedby');
});
</script>
Best practices
- Drop an error's id from
aria-describedbyonce the error clears. A referenced element keeps supplying its text while hidden, so hiding the message alone leaves it in the description. - List ids in the order they should read, or reference one wrapper around several paragraphs. Either works, because the referenced elements make up the entire description.
- Use it on an alertdialog to reference the alert message. Without it, assistive technology can resort to its own recovery mechanism to find the message.
- Reference elements in the same document. An id can't reach a description in an external resource.























