Toasts
A toast is the small, dismissible notification that slides in near a
corner of the screen — "Trail saved to favorites," "Message sent," that kind of thing.
Every component so far in this section opened purely from data-bs-*
attributes. Toasts are the first one that genuinely needs a line of real JavaScript, and
it's worth understanding exactly why.
Anatomy of a Toast
| Class | Role |
|---|---|
.toast | The outer element — hidden by default, role="alert" for screen readers. |
.toast-header | Small icon/title bar with a timestamp and close button. |
.toast-body | The actual message text. |
<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<strong class="me-auto">TrailMap</strong>
<small>just now</small>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Trail saved to favorites.
</div>
</div>
Why Toasts Need a Real JavaScript Call
Modals, offcanvas panels, collapses, and accordions are all things a user explicitly opens
by clicking a visible trigger — data-bs-toggle on that trigger is enough,
because there's always a click event to listen for. A toast is different: it's meant to
appear in response to something the page's own code just did — a favorite was
saved, a form submitted successfully, a background sync finished. There's no natural
"trigger element" for Bootstrap's data-attribute system to watch, so toasts are hidden by
display: none by default and need to be shown programmatically:
const toastEl = document.querySelector('#favoriteToast');
const toast = new bootstrap.Toast(toastEl);
toast.show();
new bootstrap.Modal(el), new bootstrap.Toast(el), etc.) — data attributes are just a convenience layer built on top for the click-to-open case. Toasts are one of the few where you're expected to reach for the constructor directly.Positioning with .toast-container
A bare .toast sits inline wherever it's placed in the document. Wrap it in
.toast-container with position utilities to pin it to a screen corner and
stack multiple toasts cleanly:
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<!-- .toast elements go here -->
</div>
Autohide and Delay
Toasts autohide after 5 seconds by default. Both behaviors are controlled with data
attributes on the .toast element itself — these are read when the
bootstrap.Toast instance is created, even though showing it still requires
the JS call above:
| Attribute | Effect |
|---|---|
data-bs-autohide="false" | Keeps the toast visible until the user dismisses it manually. |
data-bs-delay="3000" | Sets the autohide delay in milliseconds (default is 5000). |
Worked Example: "Trail Saved to Favorites"
A heart-icon button on a TrailMap trail card saves it to the signed-in user's favorites and confirms it with a toast in the bottom-right corner:
<!-- Trigger button, elsewhere on the page -->
<button type="button" class="btn btn-outline-danger" id="saveFavoriteBtn">
<i class="bi bi-heart"></i> Save Trail
</button>
<!-- Toast, positioned bottom-right -->
<div class="toast-container position-fixed bottom-0 end-0 p-3">
<div id="favoriteToast" class="toast" role="alert"
data-bs-delay="3000" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<i class="bi bi-heart-fill text-danger me-2"></i>
<strong class="me-auto">TrailMap</strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Trail saved to favorites.
</div>
</div>
</div>
<!-- JS: fire the toast when the button is clicked -->
<script>
const favoriteToastEl = document.querySelector('#favoriteToast');
const favoriteToast = new bootstrap.Toast(favoriteToastEl);
document.querySelector('#saveFavoriteBtn').addEventListener('click', function () {
// ...save to favorites via your own API call...
favoriteToast.show();
});
</script>
The toast's own markup only handles its appearance and dismiss button — TrailMap's own
click handler decides when to call .show(), which is exactly the
control a "did something just succeed?" notification needs.