1.4.13 Content on Hover or Focus
WCAG 2.2 · 1.4.13 AA Perceivable
What it requires
When additional content appears on pointer hover or keyboard focus — such as a custom tooltip, a hover menu, or a definition popup — and that content can be dismissed without moving the pointer or focus, then three conditions must be met (unless the user agent itself controls the content, like a native browser title tooltip):
- Dismissable — a mechanism (typically the Esc key) lets the user dismiss the extra content without moving the pointer or keyboard focus, as long as it doesn’t obscure or replace other content.
- Hoverable — if a pointer can trigger the content, the pointer can move over the new content without it disappearing.
- Persistent — the content stays visible until the trigger is removed, the user dismisses it, or its information is no longer valid.
- Low-vision users who magnify the screen and need the pointer to travel into the popup to read it — content that vanishes en route is unreadable.
- Keyboard users who need to dismiss a tooltip that covers content without losing their place.
- Users with motor impairments for whom precise, sustained hovering is difficult, so flickering or auto-hiding content is unusable.
- Users with cognitive disabilities distracted or disoriented by content that disappears before it can be read.
How to detect it
| Check | How | Looking for |
|---|---|---|
| Dismissable | Trigger the content, then press Esc. | The popup hides without moving pointer/focus. |
| Hoverable | Hover the trigger, then move the pointer onto the popup. | The popup stays open; no flicker or gap that drops it. |
| Persistent | Trigger via hover and via keyboard focus; wait. | Content stays until dismissed or trigger leaves — no timeout. |
| Automated | axe, Lighthouse, WAVE. | Cannot reliably detect this — it is essentially manual. |
How to fix it
- Add a keyboard dismiss handler (Esc) that hides the content without moving focus or the pointer.
- Keep the popup in the DOM flow between trigger and content, or use a short close delay, so the pointer can travel onto it without it closing.
- Remove any auto-hide timers; close only on dismiss, blur, or pointer-leave of both trigger and popup.
- Trigger on both
focusandhover, and associate the popup witharia-describedbyso it is exposed to assistive technology.
<button aria-describedby="tip">Shipping</button>
<div id="tip" role="tooltip" class="tooltip" hidden>
Ships in 2–3 business days.
</div>
<script>
// show on focus AND hover; close on Esc, and only when
// both the trigger and the tooltip lose hover/focus.
// Escape: if (e.key === 'Escape') tip.hidden = true;
</script>
Copy-paste tests
Automated coverage
There is no fully automated axe-core rule that can confirm 1.4.13. Hover/focus content (tooltips, popovers) needs manual review using the console check and steps below.
Run this in the browser console
// Read-only: surfaces likely hover/focus content for review.
const nodes = document.querySelectorAll(
'[role=tooltip], [aria-describedby], [data-tooltip], .tooltip, [title]'
);
console.table([...nodes].map(el => ({
tag: el.tagName.toLowerCase(),
describedby: el.getAttribute('aria-describedby'),
title: el.getAttribute('title'),
text: el.textContent.trim().slice(0, 40)
})));
nodes.forEach(el => el.style.outline = '2px solid magenta');
What to check manually: hover and focus each trigger and confirm the content is dismissable with Escape without moving the pointer, and stays visible (hoverable) when you move the pointer onto it.