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

Manual and tooling checks
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

  1. Add a keyboard dismiss handler (Esc) that hides the content without moving focus or the pointer.
  2. 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.
  3. Remove any auto-hide timers; close only on dismiss, blur, or pointer-leave of both trigger and popup.
  4. Trigger on both focus and hover, and associate the popup with aria-describedby so 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

find-hover-focus-content.js
// 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.