Tooltip and popover implementations: opening, dismissal and clipping
Choose a tooltip or popover by how people open it, move onto its content and dismiss it. This ledger compares twenty configured implementations across focus, hover, persistence, Escape, overflow, emulated touch and a no-JavaScript path.
Choose the kind of interaction first
The ledger contains sixteen software integrations and four related native browser patterns. The native rows are auto and manual popovers, an anchored popover and a modal dialog. They share browser capabilities rather than representing four independent products. A dialog also has a different interaction contract from a tooltip; its row makes that distinction visible.
The original five entries—Floating UI, Tippy, Radix, React Aria and Bootstrap—remain. Their documentation records are kept beside the executed configurations; Tippy’s v6 property reference is one of those records.1 All twenty rows represent loaded examples. The order carries no score or recommendation.
| Name | Version | Focus | Hover | Persistence | Escape/focus | Unclipped | Touch | No JS |
|---|---|---|---|---|---|---|---|---|
| Floating UI React | 0.27.20 | Y | Y | Y | Y | Y | Y* | N |
| Tippy.js | 6.3.7 | Y | Y | Y | N | Y | Y* | N |
| Radix Tooltip | 1.4.1 | Y | Y | Y | Y | Y | N* | N |
| React Aria Components | 1.22.1 | Y | Y | Y | Y | Y | N* | N |
| Bootstrap Tooltip | 5.3.8 | Y | Y | N | N | Y | Y* | N |
| Shoelace Tooltip | 2.20.1 | Y | Y | Y | Y | partial | Y* | N |
| Spectrum Web Components Tooltip | 1.12.5 | Y | Y | Y | Y | Y | N* | N |
| Vaadin Tooltip | 25.3.4 | Y | Y | Y | Y | Y | N* | N |
| UIkit Tooltip | 3.25.27 | Y | Y | N | Y | Y | Y* | N |
| Materialize Tooltip | 1.0.0 | Y | Y | N | N | Y | Y* | N |
| Bulma Tooltip | 3.0.2 | Y | Y | N | N | N | Y* | Y |
| Microtip | 0.2.2 | Y | Y | N | N | N | Y* | Y |
| Hint.css | 3.0.0 | N | Y | N | N | N | Y* | Y |
| Balloon.css | 1.2.0 | Y | Y | N | N | N | Y* | Y |
| Ark UI Tooltip | 5.39.3 | Y | Y | Y | Y | Y | N* | N |
| Ariakit Tooltip | 0.4.42 | Y | Y | Y | Y | Y | N* | N |
| Native auto popover | Browser-native; original E1 fixture 1 | N | N | Y | Y | Y | Y* | Y |
| Native manual popover | Browser-native; original E1 fixture 1 | N | N | Y | N | Y | partial* | Y |
| Native anchored auto popover | Browser-native; original E1 fixture 1 | Y | Y | Y | Y | Y | N* | Y |
| Native modal dialog | Browser-native; original E1 fixture 1 | N | N | Y | partial | Y | partial* | N |
Y = observed; N = observed contradiction; partial = qualified; – = not tested; * = emulated.
Start with the opening contract
Floating UI’s React recipe assembles positioning and interaction hooks.2 Radix provides composed trigger and content components; Bootstrap’s tooltip is an opt-in plugin.34 Those are different implementation units. The configuration field records what the fixture author supplied, including triggers, portals, delays and persistence rules.
A tooltip should provide a short explanation associated with its trigger. Content containing controls or requiring deliberate opening needs a different contract. The Popover API supplies a browser mechanism for placing content above the surrounding page; a dialog provides a modal or non-modal interaction surface.56 Neither name alone determines the opening behaviour of a particular implementation.
React Aria’s tooltip documentation describes a deliberate boundary around touchscreen interaction and points toward alternatives.7 Treat that documented contract separately from the emulated-touch result in its configured row. A vendor’s documentation and a browser observation answer different questions, even when they agree.
Follow the awkward cases across the row
The pointer leaves the trigger and enters the content. Read focus and hover together, then follow the persistence field. Opening is only the first part of that path. Persistence describes whether the content remains available during that movement; it does not imply that interactive controls belong inside a tooltip.
Escape closes the content. Check focus as well as visibility: the field combines dismissal with focus retention. Closing an overlay and returning focus to a different element is a different outcome from closing it while focus stays on its trigger. The note identifies the before-and-after elements rather than treating every closed overlay as the same result.
The trigger sits inside a clipped container. Read the overflow field independently of opening and dismissal. The relevant field concerns a fixture inside a clipped container. A portal or top-layer implementation can differ from an element positioned inside that container; the saved configuration identifies the rendering approach. Placement and clipping should remain separate concerns when you adapt an example.
Filter, then reproduce
Use the demo to search names and select an exact observation label. It displays original comparison records without loading the packages or sending a search request. An empty result means no row matches the filter. Reset restores the complete inventory and the search field.
Y, N, partial and – retain their distinct meanings: observed behaviour, an observed contradiction, a qualified result and no established result. Emulated-touch values carry *. An unknown is not an absent feature, and a documented option is not automatically a default or an observed outcome.
Download the CSV or JSON for full notes. METHOD.md identifies the pinned files, licences, hashes, original fixtures and repeatable steps. The tested package files are kept in a separate test harness and are not republished here.
Work through the pointer-and-focus example for a small original interaction contract. Use the overflow comparison to examine local positioning, portals, the top layer and anchors. Their examples support implementation decisions without substituting their outcomes for a vendor row.
Our observation data is licensed under CC BY 4.0. The tested packages retain their own licences.
Not covered on this page
- A complete market inventory or a ranked recommendation.
- Every framework integration, nested overlay or content combination.
- A guarantee for unrecorded versions or configurations.
Sources
-
Tippy.js: All Props. v6.x documentation, displaying 6.3.7 in the initial record; accessed 24 October 2026. ↩
-
Floating UI: Tooltip. Living React recipe; accessed 24 October 2026. ↩
-
Radix Primitives: Tooltip. Initial documentation record displayed component version 1.3.0; accessed 24 October 2026. ↩
-
Bootstrap: Tooltips. 5.3 documentation channel; accessed 24 October 2026. ↩
-
MDN: Popover API. Browser API reference; accessed 24 October 2026. ↩
-
MDN: dialog. Element reference; accessed 24 October 2026. ↩
-
React Aria: Tooltip. Living documentation; accessed 24 October 2026. ↩
How we test: methodology. Found a mistake? Corrections.