webdevpuneet.com

Toast Queue — Free HTML CSS JS Snippet

Toast Queue · Modals · Plain HTML, CSS & JS · Live preview

CategoryModals

Copy & paste

Source Code

<div class="demo">
  <div class="trigger-grid">
    <button class="trig success" onclick="toast('success','Changes saved','Your profile has been updated.')">Success</button>
    <button class="trig error" onclick="toast('error','Upload failed','File too large. Max size is 10 MB.')">Error</button>
    <button class="trig info" onclick="toast('info','New version available','v2.4.0 includes performance fixes.')">Info</button>
    <button class="trig warning" onclick="toast('warning','Session expiring','You will be logged out in 5 minutes.')">Warning</button>
    <button class="trig neutral" onclick="toast('neutral','Synced','All changes backed up to Gist.')">Neutral</button>
    <button class="trig dismiss" onclick="dismissAll()">Dismiss all</button>
  </div>
</div>

<div class="toast-container" id="toast-container" aria-live="polite" aria-label="Notifications"></div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Stacks up to MAX=5 toasts: oldest dismissed when new toast would exceed limit
prepend + flex-direction: column-reverse: newest at DOM top, visually at bottom
CSS progress bar: animation:shrink linear, duration from DURATION constant
Hover pause: mouseenter clears timer + pauses progress, mouseleave resumes
Exit animation: slide right + scale(0.96) + max-height collapse (no gap left)
animationend removes element — no invisible click-blocking remnants
data-timer attribute stores timeout ID per toast for individual control
5 types: success/error/info/warning/neutral with colour-matched border+icon+bar

About this UI Snippet

Toast Queue — Multi-Toast Stack, Progress Bar, Hover Pause, Auto-Dismiss & Max Limit

Screenshot of the Toast Queue snippet rendered live

A toast notification queue manages multiple simultaneous toasts — stacking them, auto-dismissing each after a timeout, pausing on hover, and removing the oldest when a maximum count is reached. This is the production-grade version of a single toast notification. It handles the real-world case where multiple operations complete or fail simultaneously. This snippet provides: five semantic toast types (success, error, info, warning, neutral), a CSS progress bar that drains over the dismiss duration, hover-to-pause, animated entrance and exit, a dismiss-all button, and a configurable maximum stack size.

The toast queue architecture

Toasts are prepended to a column-reverse flex container — prepend adds at the visual bottom of the stack (newest appears below older toasts). The flex-direction: column-reverse means the newest toast is at the DOM top but visually at the bottom-right, appearing to "stack up" from the corner. Each toast gets an individual setTimeout for auto-dismiss stored in a data-timer attribute.

The CSS progress bar

Each toast contains a .toast-progress div with animation: shrink linear forwards. The animation runs for DURATION milliseconds (4000ms by default), shrinking width from 100% to 0%. The animation-duration is set as an inline style from the JavaScript constant. When the user hovers, the animation is paused via animationPlayState and a new shorter timer (1500ms) starts on mouseleave.

Hover-to-pause

On mouseenter, clearTimeout removes the pending auto-dismiss. The progress bar animation is paused. On mouseleave, the animation resumes and a new 1500ms timer starts. This gives users time to read toasts without the timer running while they are focused on the notification.

The maximum stack limit

Before adding a new toast, the queue checks the count of non-leaving toasts. If equal to MAX (5), the oldest toast (last in the column-reverse list) is dismissed first. This prevents the toast stack from growing unboundedly on rapid triggers.

The exit animation

The .leaving class triggers an exit animation: toastOut slides the toast to the right with scale(0.96) and opacity 0, while also animating max-height and padding to 0. This collapse animation removes the toast from the visual stack without leaving a gap.

Integrating with a global event bus

For framework-free apps, dispatch and listen to custom events: window.dispatchEvent(new CustomEvent("toast", { detail: { type:"success", title:"Saved!" } })). Add a listener: window.addEventListener("toast", e => toast(e.detail.type, e.detail.title, e.detail.msg)). Any module or component can now fire toasts without direct function calls. This decoupled pattern prevents circular dependencies in larger applications.

Step by step

How to Use

  1. 1
    Click the trigger buttons to show different toast typesEach button shows a toast with a matching colour, icon, and progress bar. Hover a toast to pause its timer. Add 6 toasts to see the oldest one auto-dismiss when the stack limit is reached.
  2. 2
    Call toast() from anywhere in your codetoast("success", "Saved!", "Optional description") — first arg is the type, second is the title, third is an optional message. Call from API callbacks, form handlers, or any async operation.
  3. 3
    Change the auto-dismiss durationUpdate const DURATION = 4000 at the top of the JS. The progress bar animation-duration updates automatically since it reads from this constant. Use 3000 for quick feedback toasts, 6000 for important warnings.
  4. 4
    Change the maximum simultaneous toastsUpdate const MAX = 5 to control the stack limit. The oldest toast dismisses automatically when a new toast would exceed this limit.
  5. 5
    Change the toast positionUpdate .toast-container CSS: bottom/right for bottom-right (default), top/right for top-right, bottom/left for bottom-left. For centred top toasts, use top:24px; left:50%; transform:translateX(-50%); and change flex-direction to column.
  6. 6
    Export in your formatClick "HTML" for a standalone file, "JSX" for a React component with a toast context/hook, or "Tailwind" for a React + Tailwind CSS version.

Real-world uses

Common Use Cases

API call feedback and async operation results
Show toast notifications for every async operation: save success, upload error, sync complete, validation failure. The queue handles multiple simultaneous results — if three API calls complete at once, three toasts appear and auto-dismiss independently.
Form submission and data mutation feedback
Replace alert() and inline error messages with toasts. Success toasts for saves, error toasts for failures, info toasts for background operations. The hover-pause gives users time to read error messages and copy IDs before dismissal.
System status and background job notifications
Background jobs (image processing, report generation, data export) can notify completion via toasts. The progress bar signals how long the notification will remain visible, giving users time to act on the information.
Real-time collaboration event notifications
Show toasts when teammates make changes: "Alex joined the document", "Sara made 3 edits", "Raj left the session" — alongside an activity feed for the full history. Use the neutral type for non-urgent collaboration events. The MAX limit prevents overload during active collaboration sessions.
Study toast queue architecture and CSS animation control
The queue demonstrates how to manage a collection of independently timed UI elements using setTimeout IDs stored in data attributes. The animationPlayState pause pattern is applicable to any CSS animation that needs user-controlled pausing.
E-commerce and shopping action confirmations
Cart additions, wishlist saves, coupon applications, and checkout steps all benefit from toast feedback. For undoable actions, use the snackbar with undo instead. The success variant matches the expected positive confirmation; the error variant catches failed actions (out of stock, invalid coupon) immediately.

Got questions?

Frequently Asked Questions

On mouseenter: clearTimeout(+el.dataset.timer) cancels the pending dismiss. el.querySelector(".toast-progress").style.animationPlayState = "paused" freezes the visual progress bar. On mouseleave: the progress animation resumes with animationPlayState = "running". A new setTimeout of 1500ms starts — shorter than the original duration so toasts that were hovered still dismiss reasonably quickly after the user stops hovering. The data-timer attribute holds the current timer ID for each toast independently.

Create a ToastContext: const ToastContext = React.createContext(null). In a ToastProvider, manage toasts as useState([]) and expose a toast() function via the context. Components call const { toast } = useContext(ToastContext). Render the <ToastContainer> inside the provider. This gives any component in the tree access to add toasts without prop drilling. For TypeScript, define a ToastType and use useReducer for more complex state management.

Add a button inside the toast HTML: after the toast-msg div, add <button class="toast-action" onclick="handleAction()">View details</button>. Style .toast-action with font-size:12px; font-weight:700; color:inherit; background:transparent; border:1px solid currentColor; border-radius:6px; padding:3px 10px; cursor:pointer; margin-top:6px. The action button clicking should also dismiss the toast: onclick="handleAction(); dismiss(this.closest('.toast'))".

Add a message ID to each toast: el.dataset.toastId = title + "-" + type. Before adding, check for duplicates: if (container.querySelector("[data-toast-id='" + toastId + "']")) { bump animation on existing toast instead of creating new. }. This prevents "Changes saved" from appearing 5 times if the user clicks save rapidly. The bump animation (brief scale up and down) communicates that a duplicate was received without adding visual clutter.