Quick answer: Bootstrap 5 tooltips and popovers are opt-in components that you must initialise with JavaScript — new bootstrap.Tooltip(el) and new bootstrap.Popover(el). Add data-bs-toggle="tooltip" with a title, or data-bs-toggle="popover" with data-bs-content. Popovers are built on top of tooltips, so they share every option and the same Popper positioning engine. The single most common mistake is adding the markup and expecting it to work with no initialisation — nothing happens until you call it.
Part of our Bootstrap series. If the framework is not on your page yet, run through getting started with Bootstrap 5 first.
Initialising tooltips and popovers
Unlike modals and dropdowns, these two components do not auto-initialise from data attributes. You enable them once, then the attributes do the rest.
<button type="button" class="btn btn-secondary"
data-bs-toggle="tooltip" data-bs-placement="top"
title="Saved to your drafts">Draft</button>
<button type="button" class="btn btn-primary"
data-bs-toggle="popover" data-bs-title="Heads up"
data-bs-content="Popovers can hold much longer text.">Details</button>
// Enable every tooltip and popover on the page
const tooltips = document.querySelectorAll('[data-bs-toggle="tooltip"]');
tooltips.forEach((el) => new bootstrap.Tooltip(el));
const popovers = document.querySelectorAll('[data-bs-toggle="popover"]');
popovers.forEach((el) => new bootstrap.Popover(el));
// Optional: dismiss every popover when the user clicks outside it
document.addEventListener('click', (e) => {
popovers.forEach((el) => {
if (!el.contains(e.target)) bootstrap.Popover.getInstance(el)?.hide();
});
});
Tooltips also need data-bs-toggle="tooltip" on the trigger and a non-empty title; popovers replace the title with data-bs-title and use data-bs-content for the body. If you initialise a tooltip and also want it on a disabled button, wrap the button in a span and put the tooltip on the wrapper — disabled elements do not fire the mouse events the tooltip needs.
Options shared by both components
| Option | Default | Effect |
|---|---|---|
| placement | top | top, bottom, left, right, or an auto variant like auto-end |
| trigger | hover focus | click, focus, hover or manual |
| html | false | Allow HTML inside the content when true |
| delay | 0 | Milliseconds before showing or hiding |
| container | false | Append to a specific element to fix clipping in overflow containers |
| Difference | Tooltip | Popover |
|---|---|---|
| Content source | title attribute | data-bs-content attribute |
| Typical length | A few words | A sentence or two, or rich markup |
| Has a title row | No | Yes, via data-bs-title |
| Built on | Popper | Tooltip, so it inherits all options |
Triggering manually
Set trigger: 'manual' when you want to control visibility from your own code — a validation message that appears only after the user submits, for example. You then call show() and hide() yourself.
const el = document.querySelector('#email');
const tip = new bootstrap.Tooltip(el, { trigger: 'manual' });
// on submit failure
tip.show();
// when the user fixes the field
tip.hide();
Because tooltips reposition with Popper, they can be clipped by a parent with overflow: hidden — a common problem inside scrolling tables and modals. Setting the container option to 'body' lifts the tooltip out of the clipping box. This is the same fix discussed in the Bootstrap modal guide for dialogs with their own scroll area.
Accessibility and touch
A tooltip triggered only by hover is invisible on a touch device. Never put information in a tooltip that the user needs in order to complete a task — keep essential guidance in visible text or in a form’s helper text. Tooltips should supplement a label, not replace it. If a control has no visible label, give it an aria-label and let the tooltip show the same words; this pattern is used throughout the forms and validation guide and the buttons guide.
Common mistakes
- No initialisation. The markup alone does nothing; you must instantiate the plugin for each element.
- Non-unique tooltips. Initialising the same element twice creates duplicate Popper instances; use
getOrCreateInstancewhen in doubt. - Popover inside a modal. It may be clipped — set the
containeroption to the modal element. - Trusting
html:truewith user input. It injects markup, so never pass untrusted content. - Hover-only triggers. Touch users never see them; keep the trigger list including focus or use click.
Tooltips are the smallest of the overlay components. Compare them with dropdown menus, modals and toasts when choosing how to surface a message.
Want help getting the details of a dense UI right? Ampersand Academy teaches front-end development one-to-one, using your own project as the curriculum.
Frequently asked questions
Why is my Bootstrap tooltip not showing?
Tooltips and popovers are opt-in and do nothing from markup alone. Enable each element in JavaScript with new bootstrap.Tooltip on the element, and make sure it has a non-empty title attribute.
What is the difference between a Bootstrap tooltip and a popover?
A tooltip shows a short title on hover and has no title row. A popover is built on top of the tooltip and can show a heading plus a longer body of content, usually on click.
How do I show a Bootstrap tooltip on a disabled button?
Disabled elements do not fire pointer events, so wrap the disabled button in a span and attach the tooltip to the span. The tooltip then appears even though the button is inert.
How do I keep a Bootstrap tooltip from being clipped inside a modal?
Set the container option to the modal element, or to body, when you initialize the tooltip. That moves the tooltip out of any scrolling or hidden-overflow parent so it is fully visible.
Can a Bootstrap popover contain HTML?
Yes, set the html option to true and pass markup through data-bs-content or the content option. Never enable it for content that includes untrusted user input.

