Skip to content

Documentation

On this page

Popover

Contextual bubbles with the Popover API (popover="auto") and CSS Anchor Positioning. The browser handles stacking, light-dismiss, and placement — no Popover plugin and no Popper.

Sizes are minified and gzip. A plugin figure includes the Bootstrap runtime that plugin imports. Shipping every plugin is bootstrap.bundle.min.js at 23.3 KB gzip, not the sum of these rows.
What runs it JavaScript
Bootstrap 5.3 Popover plugin, which includes Tooltip and Popper 15.5 KB gzip
This repo Popover API and CSS Anchor Positioning. No Popper. 0 KB

When that API is missing, this page also loads invoker-commands.js (0.8 KB gzip). See Polyfills.

Markup this component accepts. The full inventory is /components.json.
Avoid
  • command works on <button>, not <a href>.
  • No data-bs-html="true". The bubble is markup already.

How it works

  • command="toggle-popover" and commandfor replace data-bs-toggle="popover". There is no initialize-with-JS step.
  • Title and body live in the markup as .popover-header and .popover-body, not in data-bs-title / data-bs-content.
  • The bubble is .popover with popover="auto". The browser puts it in the top layer and closes it on outside click or Escape.
  • CSS Anchor Positioning tethers the bubble to the trigger that opened it (the popover invoker). Add .bs-popover-top, .bs-popover-end, .bs-popover-bottom, or .bs-popover-start instead of data-bs-placement. Default placement is right, matching Bootstrap.
  • Keep the trigger and the popover as siblings so the invoker relationship is obvious in the markup.
  • command works on <button>, not <a href>.
  • Only one popover="auto" bubble is open at a time.
  • Top-layer popovers are not clipped by overflow, so container: 'body' is not needed. Put the popover markup inside a modal if it must participate in that dialog’s focus.

Live demo

Titles and body content are real HTML in .popover-header and .popover-body. Click the button to toggle.

Popover title

And here’s some amazing content. It’s very engaging. Right?
HTML
<span class="d-inline-block">
  <button type="button" class="btn btn-lg btn-danger" command="toggle-popover" commandfor="popoverLive">
    Click to toggle popover
  </button>
  <div class="popover bs-popover-end" popover="auto" id="popoverLive">
    <div class="popover-arrow"></div>
    <h3 class="popover-header">Popover title</h3>
    <div class="popover-body">And here’s some amazing content. It’s very engaging. Right?</div>
  </div>
</span>

Four directions

Four options are available: top, right, bottom, and left. Directions are mirrored when using Bootstrap in RTL. Add .bs-popover-top, .bs-popover-end, .bs-popover-bottom, or .bs-popover-start.

Top popover
Right popover
Bottom popover
Left popover
HTML
<div class="d-flex flex-wrap justify-content-center gap-2">
  <span class="d-inline-block">
    <button type="button" class="btn btn-secondary" command="toggle-popover" commandfor="popoverTop">
      Popover on top
    </button>
    <div class="popover bs-popover-top" popover="auto" id="popoverTop">
      <div class="popover-arrow"></div>
      <div class="popover-body">Top popover</div>
    </div>
  </span>
  <span class="d-inline-block">
    <button type="button" class="btn btn-secondary" command="toggle-popover" commandfor="popoverEnd">
      Popover on right
    </button>
    <div class="popover bs-popover-end" popover="auto" id="popoverEnd">
      <div class="popover-arrow"></div>
      <div class="popover-body">Right popover</div>
    </div>
  </span>
  <span class="d-inline-block">
    <button type="button" class="btn btn-secondary" command="toggle-popover" commandfor="popoverBottom">
      Popover on bottom
    </button>
    <div class="popover bs-popover-bottom" popover="auto" id="popoverBottom">
      <div class="popover-arrow"></div>
      <div class="popover-body">Bottom popover</div>
    </div>
  </span>
  <span class="d-inline-block">
    <button type="button" class="btn btn-secondary" command="toggle-popover" commandfor="popoverStart">
      Popover on left
    </button>
    <div class="popover bs-popover-start" popover="auto" id="popoverStart">
      <div class="popover-arrow"></div>
      <div class="popover-body">Left popover</div>
    </div>
  </span>
</div>

Custom popovers

Customize appearance with CSS variables on a class on the .popover element (Bootstrap’s data-bs-custom-class injected that class from JS).

Custom popover

This popover is themed via CSS variables.
HTML
<span class="d-inline-block">
  <button type="button" class="btn btn-secondary" command="toggle-popover" commandfor="popoverCustom">
    Custom popover
  </button>
  <div class="popover bs-popover-end custom-popover" popover="auto" id="popoverCustom">
    <div class="popover-arrow"></div>
    <h3 class="popover-header">Custom popover</h3>
    <div class="popover-body">This popover is themed via CSS variables.</div>
  </div>
</span>

Dismiss on next click

popover="auto" already light-dismisses on the next click outside the bubble (and on Escape).

Dismissible popover

And here’s some amazing content. It’s very engaging. Right?
HTML
<span class="d-inline-block">
  <button type="button" class="btn btn-lg btn-danger" command="toggle-popover" commandfor="popoverDismiss">
    Dismissible popover
  </button>
  <div class="popover bs-popover-end" popover="auto" id="popoverDismiss">
    <div class="popover-arrow"></div>
    <h3 class="popover-header">Dismissible popover</h3>
    <div class="popover-body">And here’s some amazing content. It’s very engaging. Right?</div>
  </div>
</span>

Disabled elements

A disabled control cannot be a command invoker. Wrap a .btn.disabled span in a button that toggles the popover.

Disabled popover
HTML
<span class="d-inline-block">
  <button type="button" class="border-0 bg-transparent p-0" command="toggle-popover" commandfor="popoverDisabled">
    <span class="btn btn-primary disabled">Disabled button</span>
  </button>
  <div class="popover bs-popover-end" popover="auto" id="popoverDisabled">
    <div class="popover-arrow"></div>
    <div class="popover-body">Disabled popover</div>
  </div>
</span>

Accessibility

The bubble is a popover, not a dialog. Escape and a click outside close it. Invoker Commands keep aria-expanded in sync on the trigger.

Put real heading text in .popover-header. Do not rely on data-bs-title.

Browser support

Three columns, not one baseline. The same row is on the overview.
No script Polyfill No fallback
popover="auto": Chrome 114+, Firefox 125+, Safari 17+. command on the trigger, the same polyfill as the modal. CSS Anchor Positioning: Chrome 125+, Safari 26+, Firefox 147+. Without it the bubble is not attached to the trigger. .bs-popover-auto does not reorient; it matches .bs-popover-end.