Tooltip
A tooltip is a small text bubble that describes the control it is attached to.
It supplements a visible label — it never replaces one. Keep it
text-only and non-interactive: a tooltip holds a short hint, not links, buttons, or
anything a user must reach. The trigger points at the bubble with
aria-describedby, the bubble carries role="tooltip", and the
hint appears on focus and on hover and disappears again when the user moves away or
presses Esc.
Live demo
Tab to the button or hover it: the hint appears. Press Esc while it is focused to dismiss it, and move the pointer onto the bubble — it stays put (WCAG 1.4.13). The button keeps its own visible text label, so the tooltip only adds to it.
When to use
When to use a tooltip
- To add a short, supplementary hint to a control that already has a visible, programmatic name — for example clarifying what a labelled “Settings” button does.
- When the hint is purely descriptive text: a few words, no interactive content, nothing the user must scroll to or click.
- On a control that can receive focus (a
<button>, link, or form field), so keyboard users get the hint too — not just pointer users.
If you need rich, interactive, or dismissible-on-its-own content, reach for a popover or disclosure instead — not a tooltip.
Markup
Wrap a real, focusable trigger and its bubble in a .ewa-tooltip. Tie them
together with a matching aria-describedby and id, give the
bubble role="tooltip", and start it hidden. The script reveals
it on focus and hover; the CSS reveals it on :focus-within /
:hover so it still works with JavaScript off.
<span class="ewa-tooltip">
<button type="button" aria-describedby="settings-tip">Settings</button>
<span role="tooltip" id="settings-tip" class="ewa-tooltip__bubble" hidden>
Opens your account settings
</span>
</span>
Keyboard interactions
| Key / action | Result | Why it matters |
|---|---|---|
| Tab to the trigger | The tooltip appears while the trigger holds focus. | Keyboard users get the same hint pointer users get on hover. |
| Esc | Hides the tooltip without moving focus off the trigger. | WCAG 1.4.13 requires the content be dismissible without moving the pointer or focus. Focusing the trigger again re-shows it. |
| Move focus away (Tab / Shift+Tab) | The tooltip hides as focus leaves the trigger. | The hint is tied to its control, so it should not linger once you leave (supports 2.1.1 Keyboard — no pointer needed at any step). |
ARIA roles, states, and properties
The wiring is deliberately small — two attributes do the work, and there is no expanded/collapsed state to manage because a tooltip is not a toggle.
| Element | Attribute | Purpose |
|---|---|---|
Trigger (e.g. <button>) |
aria-describedby="ID" |
Points at the id of the role="tooltip" element so
the bubble is read as the trigger's description — after its name and role. |
| Bubble | role="tooltip" |
Identifies the element as a tooltip to assistive technology. It contains only text — no focusable or interactive children. |
| Bubble | hidden |
Keeps the bubble out of the page and the accessibility tree until the trigger is focused or hovered; the script and the CSS toggle it. |
- The trigger keeps its own accessible name (its visible text or an
associated label).
aria-describedbyonly adds a description on top. - Do not put
role="tooltip"on the trigger, and do not usearia-expanded— a tooltip is not an expandable control. - Removing the bubble from the DOM, or marking it
hidden, removes it from the description; the script useshiddensoaria-describedbycan stay in place.
Common mistakes
Avoid these
- Tooltip as the only label. If the control has no visible text and no associated label, a tooltip is not a substitute — the name disappears the moment the tooltip closes. Give the control a real name first, then describe it.
- Interactive content inside. Links, buttons, or form fields in a tooltip can't be reached reliably: there is no focus path into a tooltip and it closes on blur. Use a popover or disclosure for anything actionable.
- Not dismissible. A tooltip that won't go away on Esc can permanently cover content for low-vision and magnifier users — a direct failure of WCAG 1.4.13 Content on Hover or Focus.
- Not hoverable. If the bubble vanishes the instant the pointer crosses from the trigger toward it, users can't read long hints or interact with what's underneath on their own terms — also a failure of WCAG 1.4.13. Keep it visible while the pointer is over the trigger or the bubble.