Tooltips & Popovers

This section documents Bootstrap 5.x as implemented by the official Bootstrap project. No specific patch version is pinned. Unlike the other reference sections on this site, no single reference book underpins it: the content was generated with the assistance of AI from general knowledge of Bootstrap, and should be verified against the current official documentation at getbootstrap.com/docs before relying on it in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Tooltips and popovers both attach a small floating overlay to a trigger element — a short label for a tooltip, a richer title-plus-body panel for a popover. They are covered together because they share the same underlying mechanics: both are positioned by Popper.js, and, unlike the components on Interactive Components, neither one activates from data-bs-* attributes alone — both require an explicit JavaScript call to opt each element in.

Why explicit initialization is required

Bootstrap enables tooltips and popovers "opt-in" rather than automatically, for performance: computing a Popper.js position for every element that merely carries a title attribute on every page would be wasteful, so only elements the page explicitly initializes get the behavior. The standard pattern selects every element carrying the relevant data-bs-toggle value and constructs an instance for each:

const tooltipTriggers = document.querySelectorAll('[data-bs-toggle="tooltip"]');
tooltipTriggers.forEach((el) => new bootstrap.Tooltip(el));

const popoverTriggers = document.querySelectorAll('[data-bs-toggle="popover"]');
popoverTriggers.forEach((el) => new bootstrap.Popover(el));

This script must run after the DOM elements it queries exist — placed just before </body>, or inside a DOMContentLoaded listener — otherwise querySelectorAll finds nothing and no tooltip or popover on the page will ever show.

Tooltips

The markup itself only needs data-bs-toggle="tooltip" and a title attribute holding the tooltip’s text — the title is what Bootstrap’s JavaScript reads to build the tooltip’s content, and it is removed from the DOM (so the browser’s own native title tooltip never doubles up with Bootstrap’s):

<button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-placement="top"
        title="Saves the current document">
  Save
</button>

<a href="#" data-bs-toggle="tooltip" data-bs-placement="right" title="Opens in a new tab">
  External link
</a>
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach((el) => new bootstrap.Tooltip(el));

data-bs-placement accepts top, right, bottom, or left, and is only a preference — Popper.js still flips it automatically if the tooltip would otherwise render outside the viewport (for example, a top tooltip near the top edge of the page flips to bottom).

HTML content in a tooltip

By default the title text is inserted as plain text, escaping any markup it contains. Setting data-bs-html="true" allows real HTML inside the tooltip — only worth doing for trusted, static content, since it is otherwise an XSS vector if the title text ever comes from user input:

<button type="button" class="btn btn-secondary" data-bs-toggle="tooltip" data-bs-html="true"
        title="<em>Emphasized</em> tooltip text">
  Hover me
</button>

Popovers

A popover is structurally similar to a tooltip but supports both a title (the popover’s header) and a separate data-bs-content (its body), and stays open until dismissed rather than only while hovering, when combined with the focus/dismiss options below:

<button type="button" class="btn btn-primary" data-bs-toggle="popover" data-bs-placement="bottom"
        title="Dismissible popover" data-bs-content="And here's some amplifying body content.">
  Click to toggle popover
</button>
document.querySelectorAll('[data-bs-toggle="popover"]').forEach((el) => new bootstrap.Popover(el));

Popovers default to triggering on click rather than hover, which is why data-bs-toggle="popover" alone is enough to make the example above open on click without any extra configuration.

Dismiss on next click

data-bs-trigger="focus" closes the popover as soon as the user clicks anywhere else on the page (moving focus away from the trigger), which is the recommended pattern for a "dismissible on next click" popover — the trigger element must be focusable for this to work, so a plain <a> needs tabindex="0" if it lacks an href:

<button type="button" class="btn btn-secondary" data-bs-toggle="popover" data-bs-trigger="focus"
        title="Dismissible" data-bs-content="Clicking anywhere else closes this popover.">
  Dismissible popover
</button>

The JavaScript component API

Both components support the same instance-based API shape used across Bootstrap’s other stateful components (see JavaScript Behavior for the general pattern): show(), hide(), toggle(), and dispose(), retrieved either from the constructor’s return value or, for an instance created elsewhere, via bootstrap.Tooltip.getInstance(el):

const el = document.getElementById("save-button");
const tooltip = new bootstrap.Tooltip(el, {
  placement: "top",
  title: "Saves the current document",
});

tooltip.show();
tooltip.hide();
tooltip.dispose();   // removes the tooltip and its event listeners entirely

// elsewhere, without a reference to the original instance:
bootstrap.Tooltip.getInstance(el)?.hide();

dispose() matters specifically for content that is removed from the DOM dynamically (a row deleted from a table, a card removed from a list) — without disposing the tooltip/popover instance first, Popper.js keeps a reference to the now-detached element and its positioning listeners are never cleaned up, a small but real memory leak in a page that creates and destroys many such elements over its lifetime.

Custom triggers and events

The trigger option (or data-bs-trigger) accepts a space-separated combination of click, hover, focus, and manual — manual disables all automatic triggering, leaving show()/hide()/toggle() as the only way to control visibility, useful when a tooltip’s visibility should be driven by application logic rather than direct user interaction with the trigger element itself.

Choosing between them

Use a tooltip for a short, supplementary label — what an icon-only button does, an abbreviation’s expansion — content the user does not strictly need to operate the page. Use a popover when there is more to say than fits in a one-line label, or when the content should stay visible while the user reads or interacts with it, rather than disappearing the instant the pointer moves away.

See the official Tooltips docs and the official Popovers docs for the complete option and event reference.