Skip to content

Documentation

On this page

Toasts

A lightweight status message in the top layer, using popover="manual" and command / commandfor. Optional <pe-toast> adds data-delay and stacking. No Toast plugin.

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 Toast plugin 5.4 KB gzip
This repo popover=manual. Optional pe-toast for data-delay and stacking. 0 KB. Optional behavior for autohide.
Markup this component accepts. The full inventory is /components.json.
Optional <pe-toast> · src/behaviors/toast.js . data-delay autohide and corner stacking. Show and close work without it.
Avoid
  • popover="manual" has no light-dismiss. Give every toast a close control.
  • The toast does not take focus. Use role="status" or role="alert" so it is announced.

How it works

  • popover="manual" puts the toast in the top layer and keeps it open until something hides it. There is no light-dismiss.
  • command="show-popover" and command="hide-popover" show and close it. That needs no extra script.
  • :popover-open replaces .show. The container’s top-0, bottom-0, start-0, and end-0 choose the corner.

Live example

A status toast. Show opens it. Close hides it. It stays until you close it.

Bootstrap 11 mins ago
Hello, world! This is a toast message.
HTML
<button type="button" class="btn btn-primary" command="show-popover" commandfor="liveToast">
  Show live toast
</button>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div class="toast" id="liveToast" popover="manual" role="status" aria-live="polite" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Bootstrap</strong>
      <small>11 mins ago</small>
      <button type="button" class="btn-close" command="hide-popover" commandfor="liveToast" aria-label="Close"></button>
    </div>
    <div class="toast-body">
      Hello, world! This is a toast message.
    </div>
  </div>
</div>

Custom content

A toast can carry actions. Those buttons hide the same popover.

Bootstrap
Hello, world! This is a toast message.
HTML
<button type="button" class="btn btn-primary" command="show-popover" commandfor="customToast">Show custom toast</button>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div class="toast" id="customToast" popover="manual" role="status" aria-live="polite" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Bootstrap</strong>
      <button type="button" class="btn-close" command="hide-popover" commandfor="customToast" aria-label="Close"></button>
    </div>
    <div class="toast-body">
      Hello, world! This is a toast message.
      <div class="mt-2 pt-2 border-top">
        <button type="button" class="btn btn-primary btn-sm" command="hide-popover" commandfor="customToast">Take action</button>
        <button type="button" class="btn btn-secondary btn-sm" command="hide-popover" commandfor="customToast">Close</button>
      </div>
    </div>
  </div>
</div>

Color schemes

An important toast uses role=alert and aria-live=assertive. Color utilities sit on the toast.

HTML
<button type="button" class="btn btn-primary" command="show-popover" commandfor="colorToast">Show color toast</button>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div class="toast align-items-center text-bg-primary border-0" id="colorToast" popover="manual" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="d-flex">
      <div class="toast-body">Hello, world! This is a toast message.</div>
      <button type="button" class="btn-close btn-close-white me-2 m-auto" command="hide-popover" commandfor="colorToast" aria-label="Close"></button>
    </div>
  </div>
</div>

Placement

top-0 start-0 and bottom-0 end-0 on the container place the open toast.

Bootstrap
Hello, world! This is a toast message.
Bootstrap
Hello, world! This is a toast message.
HTML
<div class="d-flex flex-wrap gap-2">
  <button type="button" class="btn btn-primary" command="show-popover" commandfor="toastTopStart">Top start</button>
  <button type="button" class="btn btn-primary" command="show-popover" commandfor="toastBottomEnd">Bottom end</button>
</div>

<div class="toast-container position-fixed top-0 start-0 p-3">
  <div class="toast" id="toastTopStart" popover="manual" role="status" aria-live="polite" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Bootstrap</strong>
      <button type="button" class="btn-close" command="hide-popover" commandfor="toastTopStart" aria-label="Close"></button>
    </div>
    <div class="toast-body">Hello, world! This is a toast message.</div>
  </div>
</div>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div class="toast" id="toastBottomEnd" popover="manual" role="status" aria-live="polite" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Bootstrap</strong>
      <button type="button" class="btn-close" command="hide-popover" commandfor="toastBottomEnd" aria-label="Close"></button>
    </div>
    <div class="toast-body">Hello, world! This is a toast message.</div>
  </div>
</div>

Accessibility

Use role="status" with aria-live="polite" and aria-atomic="true" for an ordinary message. Use role="alert" with aria-live="assertive" for an important one. The toast does not take focus.

popover="manual" does not light-dismiss. Hover and focus pause optional data-delay autohide so a reader can finish the message.

Browser support

Three columns, not one baseline. The same row is on the overview.
No script Polyfill No fallback
popover="manual" with command to show and close. No light-dismiss. None for show and close. Optional pe-toast for data-delay and stacking. Without pe-toast, open toasts share one corner.

Autohide and stacking

<pe-toast> is the toast itself, with class="toast". Load src/behaviors/toast.js when you want it. data-delay is milliseconds. Omit it and the toast stays open. Hovering or focusing the toast pauses the timer and starts a full delay again when the pointer and focus have both left. Open siblings in the same .toast-container are offset so they stack. Without the module, one toast still sits in the corner, and a second one shares that corner.

Stacking is the one place this package measures an element. The behavior sets --pe-toast-index, the number of open toasts before this one, and --pe-toast-stack, the sum of their heights. CSS adds one --bs-toast-spacing per toast, so the gap is a token and not a number from JavaScript. Toasts in the top layer do not share a layout box, so a container cannot space them the way .toast-container spaces in-flow children.

When every toast in a corner is the same height, you can drop the measurement. Percentages in translate resolve against the element’s own size, so the index alone places the stack and --pe-toast-stack goes unused. The element still supplies the index, because only open toasts count toward it:

.toast[popover] {
  bottom: 1rem;
  translate: 0 calc(var(--pe-toast-index, 0) * -1 * (100% + var(--bs-toast-spacing)));
}

Stacking

Both toasts hide after 5 seconds unless the pointer or focus is inside them. Show both to see the stack.

Bootstrap just now
See? Just like this.
Bootstrap 2 seconds ago
Heads up, toasts will stack automatically.
HTML
<script type="module" src="./node_modules/bootstrap-html/src/behaviors/toast.js"></script>

<div class="d-flex flex-wrap gap-2">
  <button type="button" class="btn btn-primary" command="show-popover" commandfor="stackToastOne">Show first</button>
  <button type="button" class="btn btn-secondary" command="show-popover" commandfor="stackToastTwo">Show second</button>
</div>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <pe-toast class="toast" id="stackToastOne" popover="manual" data-delay="5000" role="status" aria-live="polite" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Bootstrap</strong>
      <small>just now</small>
      <button type="button" class="btn-close" command="hide-popover" commandfor="stackToastOne" aria-label="Close"></button>
    </div>
    <div class="toast-body">See? Just like this.</div>
  </pe-toast>
  <pe-toast class="toast" id="stackToastTwo" popover="manual" data-delay="5000" role="status" aria-live="polite" aria-atomic="true">
    <div class="toast-header">
      <strong class="me-auto">Bootstrap</strong>
      <small>2 seconds ago</small>
      <button type="button" class="btn-close" command="hide-popover" commandfor="stackToastTwo" aria-label="Close"></button>
    </div>
    <div class="toast-body">Heads up, toasts will stack automatically.</div>
  </pe-toast>
</div>