Bootstrap 5 Tooltip JS (Popper.js + TemplateFactory + Sanitizer) vs Native Popover API
Uses bootstrap.Tooltip + Popper.js — creates DOM elements, runs createPopper() for positioning, sanitizes HTML via TemplateFactory + Sanitizer on every show.
Uses Popover API (popover="manual") — element already in DOM, browser handles top-layer stacking. Show/hide via showPopover() / hidePopover(). Zero JS positioning needed.
| Metric | Bootstrap Tooltip | Native Popover API |
|---|---|---|
| Initialization time (200 instances) | - | - |
| Toggle time (10 cycles × 200 items) | - | - |
| Instance memory cost (200 instances) | - | - |
|
JS code size
tooltip.js (18.0 KB) +
template-factory.js (4.6 KB) +
sanitizer.js (3.8 KB) +
@popperjs/core
(19.7 KB min)
|
- | - |
|
CSS output size
_tooltip.scss (4.2 KB)
|
- | - |
data-bs-toggle="tooltip"
popover="manual"
createPopper() on every show, creates a new tooltip
<div> via TemplateFactory, sanitizes its HTML content
via Sanitizer, and runs JavaScript to calculate offsets and apply inline
transform styles. Native Popover API tooltips are already in the DOM
— showPopover() simply moves them to the top layer. Zero DOM creation,
zero JS positioning, zero sanitization.
<!-- Trigger -->
<button style="anchor-name: --my-tip-trigger;">
Hover me
</button>
<!-- Tooltip (Bootstrap utility classes for styling) -->
<div popover="manual" id="my-tip"
class="px-2 py-1 bg-dark text-white rounded small border-0 shadow"
style="position-anchor: --my-tip-trigger;">
Tooltip text
</div>
[popover].native-tooltip {
inset: unset; /* reset UA default */
position: fixed;
bottom: anchor(top); /* place above trigger */
left: anchor(center);
translate: -50% -4px; /* center horizontally + gap */
}
btn.addEventListener('mouseenter', () => tip.showPopover());
btn.addEventListener('mouseleave', () => tip.hidePopover());