ARIA Rule

Tooltips must have an accessible name aria-tooltip-name

An element with role="tooltip" needs a name, which is normally just the text inside it. The common way to break this is hiding that text with aria-hidden, or replacing it with an icon, so the tooltip has a role and a visible message but no accessible name. A screen reader then announces that a tooltip exists without saying what it says.

Websight reports this as ARIA tooltip nodes must have an accessible name

Who it affects

Someone using a screen reader hovers or focuses the info icon, hears tooltip, and gets none of the explanation sighted people are reading.

Someone using screen magnification sees only part of the tooltip and relies on the screen reader to fill in the rest, which cannot.

Someone using voice control cannot refer to the tooltip by its content when asking for it to be read.

Broken versus fixed

Both examples are live and rendered in a sandboxed frame. The broken one is deliberately broken.

Broken

The tooltip is on screen and reads fine. A screen reader on the info button announces: What is CVC?, button, and then nothing, because the tooltip's text is aria-hidden so it has no name to pass on.

Fixed

Announced: What is CVC?, button, The 3 digits on the back of your card. The tooltip's text is its name, and aria-describedby on the button reads it out. (The demo keeps the tooltip permanently shown; real ones appear on hover and focus.)

Show the markup behind both examples
Broken
<style>body{font-family:system-ui;padding:16px;margin:0}.row{display:flex;align-items:center;gap:6px;position:relative;width:max-content}label{font-size:14px}.i{width:18px;height:18px;border-radius:50%;border:0;background:#2b6cb0;color:#fff;font-size:12px;font-weight:700;cursor:default}.tip{position:absolute;left:0;top:28px;background:#2d3748;color:#fff;font-size:13px;padding:6px 10px;border-radius:6px;width:220px}input{display:block;margin-top:34px;width:80px}</style>
<div class="row">
  <label for="cvc">CVC</label>
  <button class="i" type="button" aria-label="What is CVC?" aria-describedby="tip">?</button>
  <div class="tip" role="tooltip" id="tip"><span aria-hidden="true">The 3 digits on the back of your card</span></div>
</div>
<input id="cvc" inputmode="numeric" maxlength="4">
Fixed
<style>body{font-family:system-ui;padding:16px;margin:0}.row{display:flex;align-items:center;gap:6px;position:relative;width:max-content}label{font-size:14px}.i{width:18px;height:18px;border-radius:50%;border:0;background:#2b6cb0;color:#fff;font-size:12px;font-weight:700;cursor:default}.tip{position:absolute;left:0;top:28px;background:#2d3748;color:#fff;font-size:13px;padding:6px 10px;border-radius:6px;width:220px}input{display:block;margin-top:34px;width:80px}</style>
<div class="row">
  <label for="cvc">CVC</label>
  <button class="i" type="button" aria-label="What is CVC?" aria-describedby="tip">?</button>
  <div class="tip" role="tooltip" id="tip">The 3 digits on the back of your card</div>
</div>
<input id="cvc" inputmode="numeric" maxlength="4">

Test it by hand in two minutes

  1. Search the page source for role="tooltip". Each one should contain plain text, or have an aria-label or aria-labelledby.
  2. Check nothing inside the tooltip is aria-hidden, and that the tooltip is not hidden with display: none at the moment it is supposed to be read.
  3. Check the trigger (the icon or field) points at the tooltip with aria-describedby, so the text is read when the trigger gets focus.
  4. Turn on VoiceOver (Cmd+F5) or NVDA and Tab to the trigger. After its name you should hear the tooltip text. If you only hear the word tooltip, the name is missing.

The fix

Before
<div role="tooltip" id="tip"><span aria-hidden="true">The 3 digits on the back of your card</span></div>
After
<div role="tooltip" id="tip">The 3 digits on the back of your card</div>

Let the text be the name. If the tooltip holds only an icon, add aria-label with the same meaning. And give the trigger aria-describedby="tip" so the tooltip is read in context.

Tooltip that is only an icon

Before
<div role="tooltip" id="lock"><svg>...</svg></div>
After
<div role="tooltip" id="lock" aria-label="Your details are encrypted"><svg aria-hidden="true">...</svg></div>

An icon does not name anything. Say in words what the icon means.

Tooltip not linked to its trigger

Before
<button aria-label="Help">?</button>
<div role="tooltip" id="tip">Enter the code we emailed you</div>
After
<button aria-label="Help" aria-describedby="tip">?</button>
<div role="tooltip" id="tip">Enter the code we emailed you</div>

The name check passes without this, but the text is only useful if the trigger references it.

Common mistakes

  • Hiding the tooltip text with aria-hidden to stop it being read twice, which stops it being read at all.
  • Putting the tooltip text in a title attribute on the icon and the role="tooltip" on an empty div.
  • Using role="tooltip" for a rich popover with links and buttons; a tooltip is plain text only.
  • Showing the tooltip on hover only, so keyboard users never trigger it.
  • Naming the tooltip tooltip or info.

WCAG criteria this rule maps to

axe-core tags this rule as WCAG 2.2 level A. It is one of the checks for:

The scanner can see a tooltip whose computed name is empty. It cannot tell whether the trigger is wired to it, or whether it appears on keyboard focus, so check both by hand. Automated tools find only part of the accessibility problems on a page; a pass on this rule is not a pass on the criterion.

Scan your own page for this and 63 other checks

Open any page in Chrome, click Websight, and get a score out of 100 with every issue explained and a draft fix snippet per element.

Add Websight to Chrome

Free scans, no account, nothing leaves your computer. Automated tools find only part of the problems; the extension says so on every report.