( Robust / WCAG 4.1.2 )
ARIA tooltip has no accessible name
What is this issue?
An element carrying role="tooltip" has no accessible name and no meaningful text content, the text a screen reader announces to identify an element, which for a tooltip comes primarily from its own visible content rather than an external aria-label.
A tooltip’s entire job is to supply a short piece of supplementary text, typically referenced by a trigger element’s aria-describedby. When the tooltip element itself is empty (no text node, no child content), there’s nothing for the accessible name computation to find, so assistive technology either announces the tooltip as blank or the reference produces no additional description at all.
Why does this matter?
Every other rule in this cluster is about a widget’s own name being missing while it does something useful anyway: a button still works, a switch still toggles. A tooltip with no content does nothing at all. Its sole purpose is conveying text, so an empty tooltip is a complete, silent failure rather than a partial one.
This most often happens as a side effect of how tooltips are usually implemented: the tooltip div exists in the DOM from page load, hidden, and gets its text filled in by JavaScript right before it’s shown. If that population logic has a bug (a race condition, a missing data field, a broken template string), the tooltip element renders and gets referenced by aria-describedby, but contains nothing.
Who is affected?
- Screen reader users: reach a referenced tooltip via
aria-describedbyand hear either nothing or a truncated pause where the supplementary description should be, with no way to know information was supposed to be there at all. - Keyboard users: who trigger tooltips by focusing the associated control (rather than hovering with a mouse) get the same missing content, and unlike a sighted mouse user, have no visual fallback to notice the tooltip box is rendering empty.
What users experience
Ines uses NVDA on Windows to fill out a password field on a signup form that shows a tooltip explaining the password requirements when the field receives focus. The tooltip element exists with role="tooltip" and is correctly referenced by the input’s aria-describedby, but its text is populated by a JavaScript call that silently fails for a subset of locales, including hers. NVDA announces the input’s name and role, then nothing further (no password requirements), and she submits a guess that gets rejected by validation with no explanation of what was wrong in the first place.
How do I fix it?
Make sure the tooltip element always contains the text it’s meant to display before it becomes visible or gets referenced by aria-describedby. This works because the accessible name computation reads whatever’s in the DOM at the moment assistive technology reaches the element: if the text populates the DOM reliably and early, there’s nothing for this rule to catch.
Trigger the tooltip on both :hover and :focus (or :focus-visible) on the associated control, not hover alone. This works because keyboard users never trigger a hover state, so a hover-only tooltip is invisible to them regardless of whether its text content is correct.
If a tooltip’s content genuinely depends on an asynchronous data fetch, render a fallback string (not an empty element) until the real content arrives, and update the DOM once it does; an empty state should never be the version a screen reader might land on mid-load.
Code Examples
<label for="password">Password</label>
<input id="password" type="password" aria-describedby="tip-1">
<div role="tooltip" id="tip-1"></div><label for="password">Password</label>
<input id="password" type="password" aria-describedby="tip-1">
<div role="tooltip" id="tip-1">
Password must be at least 8 characters and include a number.
</div>The fix here is content, not markup: the role="tooltip" and aria-describedby wiring were already correct in the “before” example; the element simply never received the text it was supposed to contain. Once the tooltip always renders with real content, the same wiring reads correctly for screen readers.
Common Mistakes
Mistake: “The tooltip shows visually when I hover over it, so it must be working.” A sighted developer testing by hovering with a mouse only catches a hover-triggered rendering bug, not an empty-DOM-at-load bug or a focus-trigger gap. Test by tabbing to the trigger with a keyboard and checking what a screen reader announces, not just what appears visually on mouse hover.
Mistake: “aria-describedby alone makes the tooltip accessible, regardless of its content.” aria-describedby only creates the reference between the trigger and the tooltip element; it doesn’t supply any text itself. If the referenced element is empty, the reference resolves to nothing, and the fix has to happen inside the tooltip element, not in the attribute pointing at it.
Mistake: “The tooltip only shows on hover, so keyboard users don’t need it.” Keyboard users frequently need the exact same supplementary information a mouse-hovering sighted user gets: password rules, field format hints, icon explanations. A tooltip that only opens on :hover and never on :focus excludes keyboard users from content everyone else can see.
How RedFlag Detects This
Automated: axe-core rule, runs on every scan. RedFlag calls axe-core’s aria-tooltip-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="tooltip" and checks whether the accessible name computation resolves to non-empty text at the moment the page is scanned.
False negative: the scan captures a snapshot of the DOM at scan time. A tooltip that’s empty on initial load but gets populated later by a slow asynchronous fetch may read as passing if the scan happens to run after the content arrives, even though a real user with a slower connection could still encounter it empty. False positive: a tooltip element that intentionally starts empty and is only ever populated immediately before becoming visible (never referenced while empty) can be flagged even though no user ever actually encounters it blank; the scan checks the DOM state, not runtime timing. Manual step: trigger every tooltip by both hover and keyboard focus and confirm content is present at the moment it becomes visible or referenced, not just at some point during the page’s lifecycle.
Manual Testing
- Open the page in Chrome or Firefox with NVDA or JAWS running.
- Tab to each control that has an associated tooltip (an info icon, a password field, a form field with a format hint).
- Confirm the tooltip becomes visible on focus, not only on mouse hover.
- Listen to what NVDA or JAWS announces; the tooltip’s text should be read as part of the control’s description, not silence or a truncated pause.
- Repeat on a slower network throttle in DevTools if the tooltip’s content loads asynchronously, to catch a race condition a fast connection would hide.
Related WCAG Success Criteria
4.1.2 Name, Role, Value: Every interface component must expose a name, role, and current value to assistive technology. An empty tooltip has a role but no name and no content, which is the most complete version of this criterion’s requirement going unmet.
1.3.1 Info and Relationships: Information conveyed visually must also be available programmatically. A tooltip that renders visible text on screen but nothing in the accessible name computation breaks that equivalence: the information exists for sighted users and not for screen reader users at the exact same moment.
Related Issues
ARIA command has no accessible name covers the trigger side of many tooltip patterns: an icon-only info button that opens a tooltip often needs its own accessible name in addition to the tooltip content itself.
ARIA input field has no accessible name frequently pairs with this rule on the same form, since format-hint tooltips are commonly attached to custom input widgets that also need their own name.
Focused element is hidden behind a sticky header or footer is a related visibility failure worth checking alongside this rule: a tooltip can render with correct content but still be visually clipped or hidden for a focused user by page chrome.
Hidden component exposed to screen readers covers the opposite visibility mismatch: content invisible on screen but still reachable by assistive technology, the reverse of a tooltip that’s visible but empty.
aria-braillelabel or aria-brailleroledescription has no equivalent covers the same naming family from the other direction: a tooltip’s accessible name has to exist before a braille-specific shortened version of it makes sense.
References
- W3C Understanding 4.1.2: Name, Role, Value
- ARIA Authoring Practices: Tooltip Pattern
- MDN: aria-describedby
Frequently asked questions
Does aria-describedby announce a tooltip automatically?
Yes, if the referenced element has content. aria-describedby on the triggering control makes a screen reader read the tooltip text as part of that control announcement, but only if the tooltip element itself resolves to non-empty text. An empty tooltip element connected with aria-describedby still announces nothing.
Is a tooltip role required, or does the title attribute already work as a tooltip?
The title attribute produces a native browser tooltip on mouse hover only, with inconsistent screen reader support and zero availability to touch or keyboard-only users. role="tooltip" combined with aria-describedby is the accessible alternative, since it reaches keyboard focus and screen readers reliably, not just a mouse hover.
Should a tooltip open on focus as well as hover?
Yes. A tooltip that only opens on mouse hover is invisible to keyboard-only users entirely. The trigger element needs to show the tooltip on both :hover and :focus-visible so keyboard users get the same supplementary information a mouse user sees.
Can a tooltip contain interactive content like a link or button?
No, not per the ARIA tooltip pattern. A tooltip is meant to be a short, non-interactive text description, and screen readers do not reliably let a user move focus into a tooltip to interact with content inside it. Use a popover or dialog pattern instead if interactive content is genuinely needed.
What happens if the tooltip is empty when the page loads and filled in later by JavaScript?
The accessible name computation runs against the DOM state at the moment assistive technology reads it, so a tooltip populated after a delay announces as empty if a screen reader reaches it before the content loads. Populate tooltip text before it becomes visible or referenced, not asynchronously after.