Toast
Display temporary, non-blocking notifications using the Toast plugin — suitable for status updates and non-critical alerts.
Introduction
Toasts are short-lived, non-blocking notifications that overlay page content. Unlike the notification component, toasts are transient — they appear briefly and either hide automatically or are dismissed by the user.
How they work
The Toast plugin manages visibility through CSS classes. Toasts start hidden and require a .show() call — or a data-cx-dismiss trigger — to appear. When autohide is enabled, the hide timer starts after the show transition completes and pauses while the pointer is over the toast or focus is within it. Toasts overlay content without disrupting pointer events on the page underneath.
Chassis CSS respects user accessibility preferences by automatically disabling animations when the prefers-reduced-motion media query is detected. See the reduced motion guidelines in our accessibility documentation for implementation details.
Live example
Clicking the button below instantiates a Toast and calls .show(). The toast auto-hides after 5 seconds (the default delay).
Hello, world! This is a toast message.
const toastTrigger = document.getElementById('liveToastButton')
const toastLiveExample = document.getElementById('liveToast')
if (toastTrigger) {
const toastChassis = Toast.getOrCreateInstance(toastLiveExample)
toastTrigger.addEventListener('click', () => {
toastChassis.show()
})
}Basic structure
A toast consists of a .toast element wrapping any combination of .toast-header, .toast-body, and .toast-footer regions. The header and footer carry border rules that separate them visually from the body.
<div class="toast" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>.toast-header is a flex container. Chassis's margin and spacing utilities apply directly for alignment and spacing control.
Action footer
.toast-footer creates a button row below the body, separated by a border that matches the header rule. Use it when the notification requires user acknowledgement or a follow-up action.
<div class="toast" role="status">
<div class="toast-body">
Hello, world! This is a toast message.
</div>
<div class="toast-footer">
<button type="button" class="button primary small">Take action</button>
<button type="button" class="button secondary small" data-cx-dismiss="toast">Close</button>
</div>
</div>Simplified layout
Remove .toast-header and apply flexbox utilities directly to .toast for a compact, single-region layout.
<div class="toast justify-content-between" role="status">
<div class="d-flex">
<div class="toast-body">
Hello, world! This is a toast message.
</div>
<button type="button" class="close-button m-small ms-auto" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
</div>Placement
.toast-container is position: absolute by default. Combine it with position utilities to pin toasts to a viewport edge (position-fixed) or to a corner within a relatively-positioned ancestor. Add a spacing utility to keep toasts from touching the container edge.
<div class="toast-container p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed top-0 start-0 p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed top-0 start-50 translate-middle-x p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed top-0 end-0 p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed top-50 start-0 translate-middle-y p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed top-50 start-50 translate-middle p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed top-50 end-0 translate-middle-y p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed bottom-0 start-0 p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div><div class="toast-container position-fixed bottom-0 start-50 translate-middle-x p-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</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-medium">
<div class="toast show" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header">
<svg aria-hidden="true" class="cxd-placeholder-image rounded me-xsmall" height="20" preserveAspectRatio="xMidYMid slice" width="20" xmlns="http://www.w3.org/2000/svg"><rect width="100%" height="100%" fill="#00A4CC" /></svg>
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>
</div>Stacking
Toasts inside a .toast-container stack vertically, separated by --toast-spacing (derived from $container-padding-x). The container itself uses width: max-content so it sizes to the widest toast.
<div class="toast-container position-static">
<div class="toast" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small class="fg-subtle">just now</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
See? Just like this.
</div>
</div>
<div class="toast" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small class="fg-subtle">2 seconds ago</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Heads up, toasts will stack automatically.
</div>
</div>
</div>Notification regions
For UIs that generate multiple notifications, wrap .toast-container in an aria-live region and position the container with inset utilities. The container sits outside normal document flow, so toasts append without shifting page content.
<div aria-live="polite" aria-atomic="true" class="position-relative">
<div class="toast-container top-0 end-0 p-medium">
<div class="toast" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small class="fg-subtle">just now</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
See? Just like this.
</div>
</div>
<div class="toast" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small class="fg-subtle">2 seconds ago</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Heads up, toasts will stack automatically.
</div>
</div>
</div>
</div>Theming
Toasts inherit the context color system and the translucent background variant from the Chassis component layer.
Context variants
Apply .context and a context color class to tint the toast. Add .solid for full-color backgrounds with inverted text.
<div class="toast-container position-static">
<div class="toast context primary" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small class="fg-main">just now</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
See? Just like this.
</div>
</div>
<div class="toast context primary solid" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small class="fg-main">2 seconds ago</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Heads up, toasts will stack automatically.
</div>
</div>
</div>Translucent
.translucent applies a semi-transparent background. Use it when toasts appear over rich or patterned content.
<div class="toast translucent" role="status">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small class="fg-subtle">11 mins ago</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>Chassis CSS respects user accessibility preferences by automatically disabling translucency effects when the prefers-reduced-transparency media query is detected. Note that this media feature is currently only supported in Chromium-based browsers — Safari and Firefox do not yet implement it.
Color utilities
Chassis color and background utilities apply directly to .toast. Pair a border utility with matching foreground and background classes for semantic coloring.
<div class="toast border-danger bg-white fg-danger justify-content-between" role="alert">
<div class="d-flex">
<div class="toast-body">
Hello, world! This is a toast message.
</div>
<button type="button" class="close-button fg-black m-small ms-auto" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
</div>Accessibility
Toasts carry live-region semantics that drive screen reader announcements. The role, timing, and interactive-element decisions here determine whether assistive technology users receive the notification at all.
ARIA roles
The ARIA role determines announcement urgency. Most toasts convey confirmations or informational updates — use role="status" for those. Reserve role="alert" for errors and messages requiring immediate attention, such as failed operations or session timeouts. Both roles carry implicit aria-live semantics, so no separate aria-live attribute is needed.
See the notification component's ARIA roles section for a full breakdown, including a heuristic table by context variant.
Autohide timing
The autohide timer starts after the show transition completes and pauses whenever the pointer is over the toast or focus is within it — the countdown resumes only after both leave. Set delay to a value that gives users enough time to read the full message before the timer begins. For toasts with action buttons, set autohide: false and provide a close button so users control dismissal.
<div class="toast" role="status" data-cx-autohide="false">
<div class="toast-header">
<img src="..." class="rounded me-xsmall" alt="...">
<strong class="me-auto">Chassis</strong>
<small>11 mins ago</small>
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Close"></button>
</div>
<div class="toast-body">
Hello, world! This is a toast message.
</div>
</div>Avoid placing interactive controls — buttons, links — inside auto-hiding toasts. Keyboard and screen reader users may not have enough time to reach or activate them before the toast disappears.
When to use alternatives
For form validation errors or information users must act on before continuing, use the notification component instead. Notifications persist until dismissed and support inline placement near the content they describe.
JavaScript API
The Toast plugin handles show/hide transitions and autohide timing. Import the Toast class from the Chassis module:
import { Toast } from '@chassis-ui/css'Triggers
The data-attribute API wires up dismissal without any JavaScript on the page beyond the bundled plugin:
Enable dismissal with the data-cx-dismiss attribute on a button within the toast:
<button type="button" class="close-button" data-cx-dismiss="toast" aria-label="Dismiss"></button>Or on a button outside the toast using the additional data-cx-target attribute:
<button type="button" class="close-button" data-cx-dismiss="toast" data-cx-target="#my-toast" aria-label="Dismiss toast"></button>closed.cx.toast event to set focus to an appropriate element.Initialization
For programmatic control — calling methods or listening to events — instantiate each .toast element with the Toast class:
const toastElements = document.querySelectorAll('.toast')
const toasts = [...toastElements].map(element => new Toast(element, options))For dismiss-only functionality, manual initialization is not required. data-cx-dismiss="toast" initializes the plugin automatically on first interaction.
See the triggers section for details.
Options
Options are set via data-cx-* attributes or passed to the constructor as an object. Attribute names use the kebab-case form of the option name — data-cx-custom-class, not data-cx-customClass. Attribute values are parsed to their native types:"true" → true, "0" → 0, and valid JSON strings to objects.
Use data-cx-config to pass multiple options as a JSON string:data-cx-config='{"delay":200}'. Individual data-cx-* attributes take precedence over data-cx-config. You can also use JSON values in individual attributes, such as data-cx-delay='{"show":100,"hide":200}'.
When initializing components, Chassis merges configurations from multiple sources in this priority order: default settings, data-cx-config values, individual data-cx-*attributes, and finally any JavaScript object options. Values defined later in this sequence override earlier ones.
| Name | Type | Default | Description |
|---|---|---|---|
animation | boolean | true | Applies a CSS fade transition on show and hide. |
autohide | boolean | true | Hides the toast automatically after delay milliseconds. The timer pauses while the pointer is over the toast or focus is within it. |
delay | number | 5000 | Milliseconds to wait before hiding. Only applies when autohide is true. |
Methods
The plugin exposes five instance methods and two static lookup methods for programmatic control:
All Chassis CSS component methods are asynchronous and initiate CSS transitions. Methods return immediately when the transition begins, not when it completes. Calling methods on components that are already transitioning will be ignored to prevent conflicts. Learn more about Chassis JavaScript patterns.
| Method | Description |
|---|---|
dispose | Destroys the instance and removes stored data from the element. |
getInstance | Static — returns the existing instance bound to a DOM element, or null. Example: Toast.getInstance(element) |
getOrCreateInstance | Static — returns the existing instance or creates one. Example: Toast.getOrCreateInstance(element) |
hide | Begins the hide transition. Returns immediately; listen for hidden.cx.toast for completion. |
isShown | Returns true if the toast currently has the .show class. |
show | Begins the show transition. Returns immediately; listen for shown.cx.toast for completion. |
toggle | Calls show() if hidden, hide() if shown. |
import { Toast } from '@chassis-ui/css'
const toast = Toast.getOrCreateInstance('#myToast')
toast.show()
toast.hide()
if (toast.isShown()) {
toast.toggle()
}Events
Each lifecycle transition fires a pair of events — one immediately when the method is called and one when the transition ends. Listen on the .toast element itself.
| Event | Description |
|---|---|
hide.cx.toast | Fired immediately when hide() is called. |
hidden.cx.toast | Fired when the hide transition has completed. |
show.cx.toast | Fired immediately when show() is called. |
shown.cx.toast | Fired when the show transition has completed. |
import { Toast } from '@chassis-ui/css'
const toastElement = document.getElementById('myToast')
toastElement.addEventListener('hidden.cx.toast', () => {
// hide transition complete — clean up or queue the next notification
})
toastElement.addEventListener('shown.cx.toast', () => {
// show transition complete — start any timers or tracking
})CSS
This component can be customized through Sass variables at compile time.
Custom properties
This component exposes CSS custom properties to control its appearance at runtime.
--padding-y: var(--toast-padding-y, #{$toast-padding-y});
--padding-x: var(--toast-padding-x, #{$toast-padding-x});
--spacing: var(--toast-spacing, #{$toast-spacing});
--max-width: var(--toast-max-width, #{$toast-max-width});
@include clamp($toast-font-size, --font-size);
--fg-color: var(--toast-fg-color, #{$toast-fg-color});
--bg-color: var(--toast-bg-color, #{$toast-bg-color});
--border-width: var(--toast-border-width, #{$toast-border-width});
--border-color: var(--toast-border-color, #{$toast-border-color});
--border-radius: var(--toast-border-radius, #{$toast-border-radius});
--box-shadow: var(--toast-box-shadow, #{$toast-box-shadow});
--header-fg-color: var(--toast-header-fg-color, #{$toast-header-fg-color});
--header-bg-color: var(--toast-header-bg-color, #{$toast-header-bg-color});
--header-border-color: var(--toast-header-border-color, #{$toast-header-border-color});Sass variables
This component uses Sass variables in scss/config/_defaults.scss to define its defaults.
$toast-max-width: 22.5rem; //360px;
$toast-padding-x: .75rem;
$toast-padding-y: .5rem;
$toast-font-size: .875rem;
$toast-fg-color: var(--fg-main);
// $toast-bg-color: #{to-opacity(var(--bg-main), var(--opacity-dim-main))};
$toast-bg-color: var(--bg-main);
$toast-border-width: var(--border-width-medium);
$toast-border-color: var(--border-subtle);
$toast-border-radius: var(--border-radius-medium);
$toast-box-shadow: var(--box-shadow-medium);
$toast-spacing: $container-padding-x;
$toast-header-fg-color: var(--fg-main);
$toast-header-bg-color: var(--dim-slight);
$toast-header-border-color: $toast-border-color;