Toasts

Toasts can be used to show notifications to users via lightweight and easily customizable alert boxes.

Overview #

Things to know when using the toast plugin:

  • Toasts are opt-in for performance reasons, so you must initialize them yourself.
  • Toasts will automatically be hidden if you do not specify autohide: false.
  • Toasts are very slightly translucent to blend in with what's below them.

Toasts can be created by adding the .toast class to a <div>. To encourage extensible and predictable toasts, we recommend a header (.toast-header) and body (.toast-body). Toast headers use display: flex, allowing easy alignment of content thanks to our margin and flexbox utilities. Toasts are as flexible as you need and have very little required markup. At a minimum, we require a single element to contain your "toasted" content and strongly encourage a dismiss button.

HTML
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true">
  <div class="toast-header">
    <img src="..." class="rounded me-2" alt="...">
    <strong class="me-auto">Halfmoon</strong>
    <small>11 mins ago</small>
    <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
  </div>
  <div class="toast-body">
    Hello, world! This is a toast message.
  </div>
</div>

Live example #

Click the button below to show a toast (positioned with our utilities in the lower right corner) that has been hidden by default.

HTML
<button type="button" class="btn btn-primary" id="live-toast-btn">Save ticket</button>

<div class="toast-container position-fixed bottom-0 end-0 p-3">
  <div id="live-toast" class="toast" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="toast-header">
      <img src="..." class="rounded me-2" alt="...">
      <strong class="me-auto">Success!</strong>
      <small>Just now</small>
      <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
    <div class="toast-body">
      Your ticket has been saved successfully.
    </div>
  </div>
</div>
JavaScript
const toastTrigger = document.getElementById("live-toast-btn");
const toastLiveExample = document.getElementById("live-toast");
if (toastTrigger) {
  const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample);
  toastTrigger.addEventListener("click", () => {
    toastBootstrap.show();
  });
}

Stacking #

You can stack toasts by wrapping them in a container with the .toast-container class, which will vertically add some spacing.

HTML
<div class="toast-container position-static">
  <div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="toast-header">
      <img src="..." class="rounded me-2" alt="...">
      <strong class="me-auto">Halfmoon</strong>
      <small>11 mins ago</small>
      <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
    <div class="toast-body">
      Hello, world! This is a toast message.
    </div>
  </div>
  <div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true">
    <div class="toast-header">
      <img src="..." class="rounded me-2" alt="...">
      <strong class="me-auto">Halfmoon</strong>
      <small>11 mins ago</small>
      <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
    </div>
    <div class="toast-body">
      Hello, world! This is a toast message.
    </div>
  </div>
</div>

Custom content #

Customize your toasts by removing sub-components, tweaking them with utilities, or by adding your own markup. Two examples are shown below—one is a simple toast, the other is a toast with controls. Both toasts are missing the default .toast-header.

HTML
<!-- Simple toast -->
<div class="toast fade show" 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 me-2 m-auto" data-bs-dismiss="toast" aria-label="Close"></button>
  </div>
</div>

<!-- Toast with controls -->
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true">
  <div class="toast-body">
    Are you sure you want to share the files in this folder with your team?
    <div class="mt-3 pt-3 border-top text-end">
      <button type="button" class="btn btn-secondary" data-bs-dismiss="toast">Cancel</button>
      <button type="button" class="btn btn-primary">Confirm</button>
    </div>
  </div>
</div>

Color schemes #

Building on the above example, you can create different toast color schemes with our color and background helpers. Here we've added .text-bg-{color} to the .toast, and also added data-bs-theme="dark" directly to the close button. For a crisp edge, we remove the default border with .border-0.

HTML
<div class="toast fade show text-bg-primary border-0 shadow-none" role="alert" aria-live="assertive" aria-atomic="true">
  <div class="d-flex">
    <div class="toast-body">
      Hello, world! This is a toast message.
    </div>
    <div class="me-2 m-auto">
      <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close" data-bs-theme="dark"></button>
    </div>
  </div>
</div>
HTML
<div class="toast fade show text-bg-info border-0 shadow-none" role="alert" aria-live="assertive" aria-atomic="true">
  <div class="d-flex">
    <div class="toast-body">
      Hello, world! This is a toast message.
    </div>
    <div class="me-2 m-auto">
      <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close" data-bs-theme="dark"></button>
    </div>
  </div>
</div>

Placement #

Place toasts with custom CSS as you need them. The top right is often used for notifications, as is the top middle. If you're only ever going to show one toast at a time, put the positioning styles right on the .toast. However, it is highly recommended to always use .toast-container for the benefit of auto-stacking. In this case, put the positioning styles on the .toast-container.

HTML
<!-- Toast placement select form -->
<form class="specific-w-450 mw-100 mx-auto">
  <div class="mb-3">
    <label class="form-label" for="toast-placement-select">Toast placement</label>
    <select class="form-select" id="toast-placement-select">
      <option value="" selected>Select a position...</option>
      <option value="top-0 start-0">Top left</option>
      <option value="top-0 start-50 translate-middle-x">Top center</option>
      <option value="top-0 end-0">Top right</option>
      <option value="top-50 start-0 translate-middle-y">Middle left</option>
      <option value="top-50 start-50 translate-middle">Middle center</option>
      <option value="top-50 end-0 translate-middle-y">Middle right</option>
      <option value="bottom-0 start-0">Bottom left</option>
      <option value="bottom-0 start-50 translate-middle-x">Bottom center</option>
      <option value="bottom-0 end-0">Bottom right</option>
    </select>
  </div>
</form>

<!-- Toast area and container -->
<div aria-live="polite" aria-atomic="true" class="position-relative bg-body-secondary border-docs-demo-container rounded-3 specific-w-450 mw-100 specific-h-250 mx-auto">
  <div class="toast-container p-3" id="toast-placement-container">
    <div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true">
      <div class="toast-header">
        <img src="..." class="rounded me-2" alt="...">
        <strong class="me-auto">Halfmoon</strong>
        <small>11 mins ago</small>
        <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
      </div>
      <div class="toast-body">
        Hello, world! This is a toast message.
      </div>
    </div>
  </div>
</div>
JavaScript
const toastPlacementContainer = document.getElementById("toast-placement-container");
const toastPlacementSelect = document.getElementById("toast-placement-select");
if (toastPlacementSelect) {
  toastPlacementSelect.addEventListener("change", () => {
    toastPlacementContainer.setAttribute(
      "class", `toast-container p-3 ${toastPlacementSelect.value}`
    );
  });
}

The classes used for positioning in the above example are position utilities. You can also use flexbox utilities to align toasts horizontally and/or vertically.

HTML
<div aria-live="polite" aria-atomic="true" class="d-flex justify-content-center align-items-center bg-body-secondary border-docs-demo-container rounded-3 specific-w-400 mw-100 specific-h-200 mx-auto">
  <div class="toast-container position-static p-3">
    <div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true">
      <div class="toast-header">
        <img src="..." class="rounded me-2" alt="...">
        <strong class="me-auto">Halfmoon</strong>
        <small>11 mins ago</small>
        <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
      </div>
      <div class="toast-body">
        Hello, world! This is a toast message.
      </div>
    </div>
  </div>
</div>

Accessibility #

Toasts are intended to be small interruptions to your visitors or users, so to help those with screen readers and similar assistive technologies, you should wrap your toasts in an aria-live region (opens in new tab). Changes to live regions (such as injecting/updating a toast component) are automatically announced by screen readers without needing to move the user's focus or otherwise interrupt the user. Additionally, include aria-atomic="true" to ensure that the entire toast is always announced as a single (atomic) unit, rather than just announcing what was changed (which could lead to problems if you only update part of the toast's content, or if displaying the same toast content at a later point in time). If the information needed is important for the process, e.g. for a list of errors in a form, then use the alert component instead of toast.

Note that the live region needs to be present in the markup before the toast is generated or updated. If you dynamically generate both at the same time and inject them into the page, they will generally not be announced by assistive technologies.

You also need to adapt the role and aria-live level depending on the content. If it's an important message like an error, use role="alert" and aria-live="assertive", otherwise use role="status" and aria-live="polite" attributes.

As the content you're displaying changes, be sure to update the delay timeout (e.g., using data-bs-delay) so that users have enough time to read the toast.

HTML
<div class="toast" role="alert" aria-live="polite" aria-atomic="true" data-bs-delay="10000">
  <div role="alert" aria-live="assertive" aria-atomic="true">...</div>
</div>

When using autohide: false (e.g., using data-bs-autohide="false"), you must add a close button to allow users to dismiss the toast.

HTML
<div class="toast fade show" role="alert" aria-live="assertive" aria-atomic="true" data-bs-autohide="false">
  <div class="toast-header">
    <strong class="font-monospace text-body me-auto">autohide: false</strong>
    <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
  </div>
  <div class="toast-body">
    This toast will not auto-hide. Therefore, the close button is mandatory.
  </div>
</div>

While technically it's possible to add focusable/actionable controls (such as additional buttons or links) in your toast, you should avoid doing this for auto-hiding toasts. Even if you give the toast a long delay timeout, keyboard and assistive technology users may find it difficult to reach the toast in time to take action (since toasts don't receive focus when they are displayed). If you absolutely must have further controls, we recommend using a toast with autohide: false.

JavaScript usage #

The examples on this page use data-bs-* attributes for functionality, which is usually enough to cover a majority of use-cases. You can read about triggers, options, methods, events, and more in the official Bootstrap documentation.

Toasts - Bootstrap
Continue reading on the offical documentation website

Up next
Tooltips

Help us grow

Our main goal is to make Halfmoon the go-to framework for building websites, dashboards and tools. If you believe in our mission, consider becoming a sponsor and help us grow.

You can email us directly if you have any queries. We are always happy to answer.

Subscribe for updates

We will notify you when the framework gets a substantial update. No spam ever.

Follow us on Twitter so that you can stay updated that way.