Try this right now: find one of your own custom tooltips — the little info bubble that pops up over an icon or an abbreviation — and hover over it. Now try to move your mouse toward the tooltip to read the rest of the sentence, or to click a link inside it. Did it vanish before you got there?
If it did, congratulations — you've just personally reproduced a real, named accessibility failure, not a vague UX gripe. This isn't "the tooltip feels a bit fiddly." It's a documented WCAG success criterion with a name, a number, and three specific, testable requirements that your tooltip almost certainly doesn't meet.
The fix takes about ten minutes once you know what to check. Here's the whole thing, end to end.
The Stat: WCAG Success Criterion 1.4.13 (Content on Hover or Focus, Level AA) requires that any additional content triggered by hover or keyboard focus — like a tooltip — be Dismissible, Hoverable, and Persistent. (Source: W3C)
Why This Happens to Almost Every Custom Tooltip
Nobody sets out to build an inaccessible tooltip. It happens because the easiest way to build one — onMouseEnter shows it, onMouseLeave hides it — feels correct and works fine for a sighted mouse user who never needs to read past the first line. The moment someone needs more time, more space, or a different input method, the whole thing falls apart.
Three groups hit this constantly:
- Low-vision users with screen magnification, who zoom in so far that moving from the trigger icon to the tooltip text takes real, deliberate mouse travel — travel your
onMouseLeavehandler interprets as "user is done, hide it." - Keyboard-only users, who tab to the trigger and expect the tooltip to appear on focus, stay put, and be dismissible with Escape — not vanish the instant they tab onward, or worse, never appear at all because the tooltip is wired to mouse events only.
- Users with fine-motor or tremor conditions, for whom a shaky or slow mouse path from icon to tooltip is exactly the kind of "leave and re-enter" motion that trips a naive hide-on-mouseleave listener.
None of this is exotic. It's the default behavior of the simplest possible tooltip implementation, which is exactly why it's so common — and exactly why WCAG 1.4.13 Content on Hover or Focus exists as its own dedicated success criterion.
The Three Requirements, Explained Plainly
WCAG 1.4.13 doesn't ask you to remove tooltips or dumb down your UI. It asks for three specific behaviors whenever hover or focus reveals extra content:
1. Dismissible
The user must be able to make the tooltip go away without moving their pointer or their keyboard focus. In practice, this usually means: pressing Escape closes it. A user shouldn't be forced to move their mouse away (which may be difficult) just to get the tooltip out of the way of something it's covering.
2. Hoverable
If a user can hover over the trigger to reveal the tooltip, they must also be able to move the pointer onto the tooltip itself — to select text, click a link, or simply keep reading — without the tooltip disappearing the moment the cursor leaves the trigger element. There should be no gap in hoverable area between trigger and tooltip that causes a flicker-and-vanish.
3. Persistent
The tooltip must remain visible until one of three things happens: the user dismisses it, the trigger element is no longer valid (e.g., the page navigates), or the hover/focus condition truly ends. A tooltip that times out arbitrarily after two seconds, whether or not the user is still reading it, does not meet this bar.
The Ten-Minute Audit
Before you touch any code, run this check on your existing tooltips:
| Check | How to test | Pass condition |
|---|---|---|
| Escape dismisses it | Focus or hover the trigger, press Escape | Tooltip closes immediately |
| Pointer can reach it | Hover the trigger, then move mouse toward the tooltip | Tooltip stays open the whole path |
| Focus reveals it | Tab to the trigger with only a keyboard | Tooltip appears, identical to hover behavior |
| No arbitrary timeout | Hover and simply wait | Tooltip does not disappear on its own after N seconds |
| Doesn't block content | Trigger the tooltip near other interactive elements | Nothing important is permanently obscured, or it's easily dismissed |
If your tooltip fails even one row, it fails the criterion — 1.4.13 doesn't grade on a curve.
Fixing It: What Good Markup Looks Like
You don't need to invent a pattern from scratch. The ARIA Authoring Practices Guide's Tooltip pattern documents exactly what's expected: the trigger element references the tooltip with aria-describedby, the tooltip itself carries role="tooltip", and the show/hide logic responds to both mouse and keyboard focus events — not mouse events alone.
Practical checklist for your implementation:
- Tooltip shows on both
mouseenter/mouseoverANDfocuson the trigger — never mouse-only - Tooltip hides on
mouseleavefrom both the trigger and the tooltip itself, with no gap between them -
Escapekey closes the tooltip regardless of how it was opened - Trigger has
aria-describedbypointing to the tooltip'sid - Tooltip container has
role="tooltip" - No
setTimeout-based auto-hide while the user is still hovering or focused - Tooltip content itself can receive hover without disappearing
One tempting shortcut is worth calling out explicitly: the native HTML title attribute looks like a free tooltip, but it comes with none of these guarantees baked in — it's inconsistent across browsers, invisible to most touch and keyboard interactions, and can't be styled or made dismissible in a reliable way. MDN's own documentation for the title attribute's limitations is candid about this, which is exactly why relying on title for anything beyond decorative, non-essential hints is a bad bet for accessibility.
What About Touchscreens?
There's a fourth case worth planning for that the three official requirements don't spell out directly, because touch devices don't really have a "hover" state at all: a finger either taps something or it doesn't. If your tooltip only opens on mouseenter, a touchscreen user tapping that same icon may trigger the underlying link or button instead of ever seeing the tooltip's content — or the tooltip flashes open and immediately closes because the tap also registers as a "tap elsewhere to dismiss." The practical fix is to treat a tap on the trigger as equivalent to a keyboard focus event: it opens the tooltip and keeps it open until the user taps the trigger again, taps elsewhere, or taps a visible close affordance — never on a timer, and never contingent on a hover event a touchscreen can't produce in the first place.
A Quick Litmus Test You Can Run Today
Here's the fastest possible sanity check, no dev tools required: tab through your page using only the keyboard, and every time a tooltip could appear, ask "did it appear, can I read all of it, and can I make it go away without touching my mouse?" If the answer to any part is no, you've found a real bug worth fixing this sprint — not a nice-to-have.
Custom UI components like tooltips, dropdowns, and modals are exactly the kind of thing that automated scanners catch inconsistently and manual review catches reliably. If you want to know what else in your interface might be quietly failing criteria like this one, a full accessibility audit will tell you — see what a full accessibility scan catches in your custom UI components before a user has to tell you first.
