Level AA

Tooltips and popovers triggered on hover or focus must be dismissible without moving the pointer, hoverable without vanishing, and persistent until the user or trigger releases them

1.4.13 Content on Hover or Focus

In Plain Language

1.4.13 Content on Hover or Focus (Level AA) governs any additional content that becomes visible when a pointer hovers a trigger or keyboard focus lands on it and can subsequently be hidden -- tooltips, custom dropdown menus, mouseover popovers, focus-triggered help text[1]. Three requirements apply together. Dismissible: the user can dismiss the additional content without moving pointer hover or keyboard focus, unless the content communicates an input error or does not obscure other content; the standard implementation is an Escape key handler. Hoverable: if pointer hover triggers the content, the pointer can be moved over the additional content without it disappearing -- the trigger and the popover must form one continuous hover surface. Persistent: the content remains visible until the trigger loses focus or hover, the user dismisses it, or the information is no longer valid.

Why It Matters

  • Screen-magnification users zoom into the trigger to read it, then need to move the cursor across the viewport to the popover to read its contents. If the tooltip closes the moment the cursor leaves the trigger -- or if a gap in the DOM between trigger and tooltip kills the :hover state -- the content is unreachable at any zoom level above roughly 200%.
  • A popover that covers underlying controls with no Escape handler leaves keyboard users stranded: they cannot see what is beneath it and cannot move focus away without triggering the action the popover is attached to.
  • Users with tremor, limited dexterity, or head-pointer input trigger hover content accidentally on the way to another target. Without a pointer-independent dismiss path, they cannot clear it without additional accidental triggers.
  • Auto-hide timers (setTimeout closing the popover after N seconds) assume a reading speed the user may not have. Screen-reader users, users reading with cognitive or learning disabilities, and users translating the page in real time need the content to persist until they release it.

Examples

Do: Tooltip that is dismissible, hoverable, and persistent

✔ Tooltip stays visible when hovered, and can be dismissed with Escape

<!-- Trigger element -->
<div class="trigger-wrap">
  <button aria-describedby="tip1">
    Account settings
  </button>
  <div id="tip1" role="tooltip">
    Manage your email, password,
    and notification preferences
  </div>
</div>

/* Tooltip visible on hover and focus-within */
.trigger-wrap:hover .tooltip,
.trigger-wrap:focus-within .tooltip {
  display: block;
}

// Dismiss on Escape
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape') {
    hideAllTooltips();
  }
});
Don't: Tooltip that vanishes when pointer moves toward it

✘ pointer-events: none on tooltip -- user cannot hover over it to read it

Do: Popover with Escape to dismiss

button.addEventListener('focus', showPopover)

document.addEventListener('keydown', (e) => {

  if (e.key === 'Escape') hidePopover()

})

✔ User can press Escape to dismiss without moving pointer or focus

Don't: Content that disappears on a timer

setTimeout(() => tooltip.remove(), 3000)

✘ Tooltip auto-hides after 3 seconds -- user cannot control when it disappears

How to Fix It

  1. Attach an Escape handler at the document level that closes any open tooltip or popover without changing focus or pointer position. This satisfies the Dismissible requirement and is the behaviour assistive-technology users expect from the WAI-ARIA Authoring Practices tooltip pattern[2].
  2. Do not apply pointer-events: none to the tooltip. It makes the element literally unhoverable and guarantees a Hoverable failure for any user who needs to move the cursor onto the content to read it.
  3. Bind the visibility state to a wrapper that contains both the trigger and the popover, using :hover or :focus-within on the wrapper rather than on the trigger alone. This forms a continuous hover surface so the pointer can cross from trigger to popover without the popover closing mid-transit.
  4. Render the tooltip adjacent to its trigger in the DOM, or use the native popover attribute with anchor positioning. Detached tooltips -- appended to <body> at a computed offset -- create a gap where :hover evaluates to false between the trigger and the popover.
  5. Remove auto-hide timers. Persistent means persistent: the popover closes when the user presses Escape, moves focus or pointer off both trigger and popover, or the underlying state invalidates the content. setTimeout-driven dismissal fails the criterion on its face.
  6. Verify at 200% magnification with a pointer. Zoom the page, trigger the popover, then move the cursor along the visual path a magnifier user would take to reach the content. If the popover vanishes before the cursor lands on it, the Hoverable requirement is not met regardless of what the spec-conformance checklist says.

References

  1. [1] W3C (2023). Understanding Success Criterion 1.4.13: Content on Hover or Focus. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/WCAG22/Understanding/content-on-hover-or-focus.html
  2. [2] W3C (2024). WAI-ARIA Authoring Practices Guide. W3C, Accessed 2026-04-07. https://www.w3.org/WAI/ARIA/apg/