Requires that tooltips and popups shown on hover or focus can be dismissed, hovered over and stay visible until the user is done.
Tooltips, dropdowns and popovers that appear when you hover or focus an element are convenient, but they can also be a trap. A magnifier user may move the pointer and make the tooltip disappear before they can read it, or it may cover the very content they need.
This criterion requires that when extra content appears on pointer hover or keyboard focus and then goes away again, it is dismissible (without moving hover or focus), hoverable (the pointer can move onto it without it disappearing) and persistent (it stays until the user removes the trigger, dismisses it or the information is no longer valid).
title tooltip, where the author does not change its presentation.People who use screen magnifiers and see only part of the screen. People with tremors or low dexterity who cannot hold the pointer steady. Keyboard users. People with cognitive differences who need more time to read.
The European Accessibility Act (Directive (EU) 2019/882) applies to in-scope products and services placed on the market after 28 June 2025. Recital 47 names four principles for websites and mobile applications: perceivable, operable, understandable and robust. Predictable, controllable pop-up content is part of "perceivable" and "operable".
The technical counterpart is the standard EN 301 549, which incorporates WCAG 1.4.13 by reference and turns it into separate clauses for each kind of ICT.
| Clause | Type of ICT | What it requires |
|---|---|---|
| 9.1.4.13 | Web pages | Web content must satisfy WCAG success criterion 1.4.13. |
| 11.1.4.13 | Non-web software (native mobile apps) | Software must satisfy the criterion for content that appears on pointer hover or keyboard focus. |
Whether and how the criterion applies to non-web documents is stated in clause 10 of the standard. Clause numbers follow the "9. + WCAG number" pattern of EN 301 549. In V3.2.1 the software clause is divided into further subclauses for open and closed functionality. Check the exact numbers in the standard when you cite them.
Standard version: EN 301 549 V4.1.1 (September 2026) is based on WCAG 2.2 and is the first version prepared specifically for the EAA. It has not yet been cited in the Official Journal of the European Union, so for now it is best treated as a voluntary technical route to the EAA's requirements. Once cited, it will give a presumption of conformity. The text of criterion 1.4.13 is the same in WCAG 2.1 and 2.2. It is a Level AA criterion.
A note on EAA scope: Article 2(4) of the Directive excludes certain content from the requirements, for example office file formats published before 28 June 2025 and archives that are not updated after that date. Content you publish or change after that date is not covered by these exclusions.
Directive (EU) 2019/882, EUR-Lex, opens in a new tab
Close the tooltip with Escape, even while the trigger keeps focus.
<button onmouseover="show()" onmouseout="hide()">Info</button><button aria-describedby="tip">Info</button>
<div id="tip" role="tooltip" hidden>Extra detail</div>
<script>
const b = document.querySelector("button");
const t = document.getElementById("tip");
b.addEventListener("focus", () => t.hidden = false);
b.addEventListener("blur", () => t.hidden = true);
b.addEventListener("keydown", e => { if (e.key === "Escape") t.hidden = true; });
</script>A gap between the trigger and the popup makes it vanish when the pointer crosses it. Keep them adjacent or treat both as the hover area.
.wrap:hover .pop { display: block; }
.pop { margin-top: 20px; } /* pointer leaves .wrap while crossing the gap */.wrap:hover .pop, .wrap:focus-within .pop { display: block; }
.pop { margin-top: 0; padding-top: 8px; } /* no gap to cross */A tooltip that disappears after a few seconds is not persistent.
setTimeout(() => tip.hidden = true, 3000);// Hide only on blur, mouse leave of both trigger and tip, or EscapeMake the pointer-leave logic cover both the trigger and the popup.
trigger.addEventListener("mouseleave", () => pop.hidden = true);function maybeHide(e) {
if (!trigger.contains(e.relatedTarget) && !pop.contains(e.relatedTarget)) {
pop.hidden = true;
}
}
trigger.addEventListener("mouseleave", maybeHide);
pop.addEventListener("mouseleave", maybeHide);A menu that only opens on hover is also not reachable by keyboard. Open on focus and click too.
.nav li:hover > ul { display: block; }.nav li:hover > ul,
.nav li:focus-within > ul { display: block; }A popup that hides what the user needs while it is open must be dismissible and should not cover the trigger.
.tip { position: absolute; top: 0; left: 0; /* covers the trigger */ }.tip { position: absolute; top: 100%; left: 0; }Native apps have no hover, but the rule applies to focus on a keyboard, switch or external pointer. Provide a way to dismiss and keep popovers open until the user acts.
import SwiftUI
struct InfoButton: View {
@State private var showInfo = false
var body: some View {
Button("Info") { showInfo.toggle() }
// The popover stays until the user dismisses it (tap outside or Escape on a keyboard)
.popover(isPresented: $showInfo) {
Text("Extra detail")
.padding()
.presentationCompactAdaptation(.popover)
}
// Avoid: closing it automatically after a timer
}
}import androidx.compose.foundation.layout.Column
import androidx.compose.material3.*
import androidx.compose.runtime.*
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun InfoButton() {
val tooltipState = rememberTooltipState(isPersistent = true) // stays until dismissed
TooltipBox(
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
tooltip = { PlainTooltip { Text("Extra detail") } },
state = tooltipState
) {
IconButton(onClick = { /* action */ }) {
Icon(androidx.compose.material.icons.Icons.Filled.Info, contentDescription = "Info")
}
}
}title tooltips as custom: Native browser tooltips are an exception, but they are also poorly accessible.