HTML Guides for aria-labelledby
Learn how to identify and fix common HTML validation errors flagged by the W3C Validator — so your pages are standards-compliant and render correctly across every browser. Also check our Accessibility Guides.
The aria-labelledby attribute is part of the WAI-ARIA specification and provides an accessible name for an element by referencing the id values of other elements that contain the labeling text. Without the aria- prefix, labelledby is simply an unrecognized attribute that browsers and assistive technologies will ignore. This means your SVG graphic won’t have the accessible label you intended, leaving screen reader users without a meaningful description of the content.
This issue is especially important for <svg> elements because SVG graphics are often used for icons, charts, and illustrations that need descriptive labels for accessibility. Using the incorrect attribute name means the graphic is effectively unlabeled for users who rely on assistive technology.
How to Fix It
Replace labelledby with aria-labelledby on your <svg> element. The attribute’s value should be a space-separated list of one or more id values that reference elements containing the label text.
If you want to label an SVG using text that’s already visible on the page, aria-labelledby is the ideal approach. You can also reference a <title> element inside the SVG itself.
Examples
❌ Incorrect: Using labelledby (invalid attribute)
<h2 id="chart-title">Monthly Sales</h2>
<svg labelledby="chart-title" role="img" viewBox="0 0 200 100">
<!-- chart content -->
</svg>
✅ Correct: Using aria-labelledby to reference an external heading
<h2 id="chart-title">Monthly Sales</h2>
<svg aria-labelledby="chart-title" role="img" viewBox="0 0 200 100">
<!-- chart content -->
</svg>
✅ Correct: Using aria-labelledby to reference the SVG’s own <title>
<svg aria-labelledby="icon-title" role="img" viewBox="0 0 24 24">
<title id="icon-title">Search</title>
<path d="M15.5 14h-.79l-.28-.27A6.47 6.47 0 0 0 16 9.5 6.5 6.5 0 1 0 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5z"/>
</svg>
✅ Correct: Referencing multiple label sources
You can combine multiple id values to build a composite accessible name, separated by spaces:
<h2 id="section-title">Revenue</h2>
<p id="section-desc">Q1 2024 revenue by region</p>
<svg aria-labelledby="section-title section-desc" role="img" viewBox="0 0 400 200">
<!-- chart content -->
</svg>
In this case, a screen reader would announce something like “Revenue Q1 2024 revenue by region” as the accessible name for the SVG.
Tips
- When using aria-labelledby on <svg>, also add role="img" to ensure consistent behavior across screen readers.
- If the SVG is purely decorative, use aria-hidden="true" instead of labeling it.
- The aria-labelledby attribute overrides other labeling mechanisms like aria-label or the <title> element, so use it when you want a specific label to take precedence.
The aria-labelledby attribute accepts an IDREFS value — a space-separated list of one or more id values that reference other elements in the document. The validator expects each ID in the list to be non-empty and contain at least one non-whitespace character. When the attribute is set to an empty string (aria-labelledby=""), it violates this constraint and triggers the validation error.
This issue commonly arises in templating systems and JavaScript frameworks where a variable intended to hold an ID reference resolves to an empty string. For example, a template like aria-labelledby="{{ labelId }}" will produce an empty attribute if labelId is undefined or blank.
Why this matters
The aria-labelledby attribute is one of the highest-priority methods for computing an element’s accessible name. According to the accessible name computation algorithm, aria-labelledby overrides all other naming sources — including visible text content, aria-label, and the title attribute. When aria-labelledby is present but empty or broken, screen readers may calculate the link’s accessible name as empty, effectively making the link invisible or meaningless to assistive technology users. A link with no accessible name is a significant accessibility barrier: users cannot determine where the link goes or what it does.
Beyond accessibility, an empty aria-labelledby also signals invalid HTML according to both the WHATWG HTML living standard and the WAI-ARIA specification, which define the IDREFS type as requiring at least one valid token.
How to fix it
You have several options depending on your situation:
- Reference a valid ID — Point aria-labelledby to the id of an existing element whose text content should serve as the link’s accessible name.
- Remove the attribute and use visible link text — If the link already contains descriptive text, aria-labelledby is unnecessary.
- Use aria-label instead — For icon-only links where no visible label element exists, aria-label provides a concise accessible name directly on the element.
- Conditionally render the attribute — In templates, use conditional logic to omit aria-labelledby entirely when there’s no valid ID to reference, rather than rendering an empty value.
Examples
Invalid: empty aria-labelledby
This triggers the validation error because the attribute value contains no non-whitespace characters.
<a href="/report" aria-labelledby=""></a>
Invalid: whitespace-only aria-labelledby
A value containing only spaces is equally invalid — IDREFS requires at least one actual token.
<a href="/report" aria-labelledby=" "></a>
Fixed: referencing an existing element by id
The aria-labelledby attribute points to a <span> whose text content becomes the link’s accessible name.
<a href="/report" aria-labelledby="report-link-text">
<svg aria-hidden="true" viewBox="0 0 16 16"></svg>
</a>
<span id="report-link-text">View report</span>
Fixed: referencing multiple IDs
You can concatenate text from multiple elements by listing their IDs separated by spaces. The accessible name is built by joining the referenced text in order.
<span id="action">Learn more:</span>
<span id="subject">Apples</span>
<a href="/apples" aria-labelledby="action subject">
<svg aria-hidden="true" viewBox="0 0 16 16"></svg>
</a>
In this case, the computed accessible name is “Learn more: Apples”.
Fixed: using visible link text instead
When the link already contains descriptive text, no ARIA attribute is needed. This is the simplest and most robust approach.
<a href="/report">View report</a>
Fixed: using aria-label for an icon-only link
When there is no separate visible label element to reference, aria-label provides the accessible name directly.
<a href="/search" aria-label="Search">
<svg aria-hidden="true" viewBox="0 0 16 16"></svg>
</a>
Fixed: conditional rendering in a template
If you’re using a templating engine, conditionally include the attribute only when a value exists. The exact syntax varies by framework, but here’s the general idea:
<!-- Instead of always rendering the attribute: -->
<!-- <a href="/report" aria-labelledby="{{ labelId }}"> -->
<!-- Only render it when labelId has a value: -->
<!-- <a href="/report" {{#if labelId}}aria-labelledby="{{labelId}}"{{/if}}> -->
This prevents the empty-attribute problem at its source rather than patching it after the fact.
The aria-labelledby attribute is an IDREFS attribute, meaning its value must be a space-separated list of one or more id values that exist in the document. These referenced elements collectively provide the accessible name for the element. When the value is an empty string ("") or contains only whitespace, there are no valid ID references, which violates the IDREFS requirement defined in the WAI-ARIA and HTML specifications.
This issue commonly appears when templating systems or JavaScript frameworks conditionally set aria-labelledby but output an empty string when no label ID is available. It also occurs when developers add the attribute as a placeholder with the intention of filling it in later but forget to do so.
Why this matters
An empty aria-labelledby is problematic for several reasons:
- Accessibility: Screen readers rely on aria-labelledby to announce the accessible name of an element. An empty value can cause unpredictable behavior — some screen readers may ignore the SVG entirely, while others may fall back to reading unhelpful content or nothing at all. This leaves users who depend on assistive technology without a meaningful description of the graphic.
- Standards compliance: The W3C validator flags this as an error because the HTML specification requires IDREFS attributes to contain at least one non-whitespace character. Shipping invalid HTML can signal broader quality issues and may cause problems in strict parsing environments.
- Maintainability: An empty aria-labelledby is ambiguous. It’s unclear whether the developer intended the SVG to be decorative, forgot to add a reference, or encountered a bug in their templating logic.
How to fix it
Choose the approach that matches your intent:
- Reference a labeling element by ID: If the SVG conveys meaning, add a <title> element (or another visible text element) inside or near the SVG with a unique id, then set aria-labelledby to that id. IDs are case-sensitive, so ensure an exact match.
- Use aria-label instead: If you want to provide an accessible name directly as a text string without needing a separate element, replace aria-labelledby with aria-label.
- Remove the attribute: If the SVG already has an accessible name through other means (such as visible adjacent text or a <title> child that doesn’t need explicit referencing), simply remove the empty aria-labelledby.
- Mark as decorative: If the SVG is purely decorative and adds no information, remove aria-labelledby and add aria-hidden="true" so assistive technology skips it entirely.
When generating aria-labelledby dynamically, ensure your code omits the attribute entirely rather than outputting an empty value when no label ID is available.
Examples
❌ Empty aria-labelledby (triggers the error)
<svg role="img" aria-labelledby="">
<use href="#icon-star"></use>
</svg>
The empty string is not a valid IDREFS value, so the validator reports an error.
✅ Reference a <title> element by ID
<svg role="img" aria-labelledby="star-title">
<title id="star-title">Favorite</title>
<use href="#icon-star"></use>
</svg>
The aria-labelledby points to the <title> element’s id, giving the SVG a clear accessible name of “Favorite.”
✅ Use aria-label with a text string
<svg role="img" aria-label="Favorite">
<use href="#icon-star"></use>
</svg>
When you don’t need to reference another element, aria-label provides the accessible name directly as an attribute value.
✅ Reference multiple labeling elements
<svg role="img" aria-labelledby="star-title star-desc">
<title id="star-title">Favorite</title>
<desc id="star-desc">A five-pointed star icon</desc>
<use href="#icon-star"></use>
</svg>
The aria-labelledby value can include multiple space-separated IDs. The accessible name is constructed by concatenating the text content of the referenced elements in order.
✅ Decorative SVG (no accessible name needed)
<svg aria-hidden="true" focusable="false">
<use href="#icon-decorative-divider"></use>
</svg>
For purely decorative graphics, aria-hidden="true" removes the element from the accessibility tree. Adding focusable="false" prevents the SVG from receiving keyboard focus in older versions of Internet Explorer and Edge.
A div element without an explicit role (or with role="generic") cannot have the aria-labelledby attribute because generic containers have no semantic meaning that benefits from a label.
The div element maps to the generic ARIA role by default. Generic elements are purely structural — they don’t represent anything meaningful to assistive technologies. Labeling something that has no semantic purpose creates a confusing experience for screen reader users, since the label points to an element that doesn’t convey a clear role.
The aria-labelledby attribute is designed for interactive or landmark elements — things like dialog, region, navigation, form, or group — where a label helps users understand the purpose of that section.
To fix this, you have two options: assign a meaningful ARIA role to the div, or use a more semantic HTML element that naturally supports labeling.
HTML Examples
❌ Invalid: aria-labelledby on a plain div
<h2 id="section-title">User Settings</h2>
<div aria-labelledby="section-title">
<p>Manage your account preferences here.</p>
</div>
✅ Fixed: Add a meaningful role to the div
<h2 id="section-title">User Settings</h2>
<div role="region" aria-labelledby="section-title">
<p>Manage your account preferences here.</p>
</div>
✅ Fixed: Use a semantic element instead
<h2 id="section-title">User Settings</h2>
<section aria-labelledby="section-title">
<p>Manage your account preferences here.</p>
</section>
Using a section element or adding role="region" tells assistive technologies that this is a distinct, meaningful area of the page — making the label useful and the markup valid.
The aria-labelledby attribute creates a relationship between an element and the text content that labels it. It works by pointing to the id of one or more elements whose text should be used as the accessible name. When the validator reports that aria-labelledby must point to an element in the same document, it means at least one of the id values you referenced doesn’t correspond to any element on the page.
This typically happens for a few reasons:
- Typo in the id — the aria-labelledby value doesn’t exactly match the target element’s id (remember, IDs are case-sensitive).
- The referenced element was removed — the labeling element existed at some point but was deleted or moved, and the reference wasn’t updated.
- The id exists in a different document — aria-labelledby cannot reference elements across pages, iframes, or shadow DOM boundaries. The target must be in the same document.
- Dynamic content not yet rendered — the element is inserted by JavaScript after the validator parses the static HTML.
This is primarily an accessibility problem. Screen readers and other assistive technologies rely on aria-labelledby to announce meaningful labels to users. When the reference is broken, the element effectively has no accessible name, which can make it impossible for users to understand its purpose. Browsers won’t throw a visible error, so the issue can go unnoticed without validation or accessibility testing.
To fix the issue, verify that every id referenced in aria-labelledby exists in the same HTML document. Double-check spelling and casing. If you reference multiple IDs (space-separated), each one must resolve to an existing element.
Examples
Incorrect — referencing a non-existent id
The aria-labelledby attribute points to "dialog-title", but no element with that id exists:
<div role="dialog" aria-labelledby="dialog-title">
<h2 id="dlg-title">Confirm deletion</h2>
<p>Are you sure you want to delete this item?</p>
</div>
Correct — matching id values
Ensure the id in the referenced element matches exactly:
<div role="dialog" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm deletion</h2>
<p>Are you sure you want to delete this item?</p>
</div>
Incorrect — referencing multiple IDs where one is missing
When using multiple IDs, every one must be present. Here, "note-desc" doesn’t exist:
<section aria-labelledby="note-heading note-desc">
<h3 id="note-heading">Important note</h3>
<p id="note-description">Please read carefully before proceeding.</p>
</section>
Correct — all referenced IDs exist
<section aria-labelledby="note-heading note-description">
<h3 id="note-heading">Important note</h3>
<p id="note-description">Please read carefully before proceeding.</p>
</section>
Incorrect — case mismatch
IDs are case-sensitive. "Main-Title" and "main-title" are not the same:
<nav aria-labelledby="Main-Title">
<h2 id="main-title">Site navigation</h2>
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
Correct — consistent casing
<nav aria-labelledby="main-title">
<h2 id="main-title">Site navigation</h2>
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
If you don’t have a visible labeling element on the page and don’t want to add one, consider using aria-label instead, which accepts a string value directly rather than referencing another element:
<nav aria-label="Site navigation">
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
Ready to validate your sites?
Start your free trial today.