Notifications
Ready to use Tailwind CSS notification components with production-ready, copy-paste HTML code. Use them as they are, or as a starting point to build beautiful websites.
Notifications here means the floating toast-style messages that pop up in a corner to let you know something happened, "Saved successfully", "Payment failed", that kind of thing. We also have notification panel layouts for a dropdown list of recent activity. They're designed to be visible without being intrusive. The positioning and entry animation are handled with Tailwind utilities. You wire up the show/hide logic yourself.
<div
aria-live="assertive"
class="pointer-events-none fixed inset-x-4 bottom-6 flex flex-col items-center space-y-4 sm:inset-x-6 sm:bottom-auto sm:top-6 sm:items-end"
>
<div
class="notification pointer-events-auto flex w-full max-w-sm items-start gap-x-3 rounded-xl bg-white p-4 shadow-lg ring-1 ring-inset ring-gray-200 transition-opacity"
>
<div class="flex-1">
<p class="text-sm font-semibold text-gray-900">
Succesfully posted!
</p>
<p class="mt-1 text-sm text-gray-500">
Post will be live in a few minutes.
</p>
</div>
<div class="shrink-0">
<button
type="button"
class="close relative rounded-md text-gray-400 hover:text-gray-500 focus:outline-2 focus:outline-offset-2 focus:outline-pink-500"
>
<span class="sr-only">Close</span>
<svg
aria-hidden="true"
class="size-5"
viewBox="0 0 60 60"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.573 41.6601C14.809 42.4242 14.809 43.6628 15.573 44.4269C16.3371 45.191 17.5759 45.191 18.34 44.4269L15.573 41.6601ZM31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166L31.3834 31.3834ZM28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834L28.6166 28.6166ZM44.4269 18.34C45.191 17.5759 45.191 16.3371 44.4269 15.573C43.6628 14.809 42.4242 14.809 41.6601 15.573L44.4269 18.34ZM31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834L31.3834 28.6166ZM41.6601 44.4269C42.4242 45.191 43.6628 45.191 44.4269 44.4269C45.191 43.6628 45.191 42.4242 44.4269 41.6601L41.6601 44.4269ZM28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166L28.6166 31.3834ZM18.34 15.573C17.5759 14.809 16.3371 14.809 15.573 15.573C14.809 16.3371 14.809 17.5759 15.573 18.34L18.34 15.573ZM18.34 44.4269L31.3834 31.3834L28.6166 28.6166L15.573 41.6601L18.34 44.4269ZM31.3834 31.3834L44.4269 18.34L41.6601 15.573L28.6166 28.6166L31.3834 31.3834ZM28.6166 31.3834L41.6601 44.4269L44.4269 41.6601L31.3834 28.6166L28.6166 31.3834ZM31.3834 28.6166L18.34 15.573L15.573 18.34L28.6166 31.3834L31.3834 28.6166Z"
fill="currentColor"
></path>
</svg>
<span class="absolute -inset-0.5 rounded-md"></span>
</button>
</div>
</div>
</div>
// Handle click events using event delegation
document.addEventListener("click", (event) => {
const button = event.target.closest("button");
if (button?.classList.contains("close")) {
closeBtnHandler(button);
}
});
const closeBtnHandler = (button) => {
try {
// Find the closest notification element
const notification = button.closest(".notification");
if (!notification) return;
// Add fade-out effect
notification.classList.add("opacity-0");
// Remove the notification after the transition
const transitionDuration =
parseFloat(getComputedStyle(notification).transitionDuration) *
1000 || 150;
setTimeout(() => {
notification.remove();
}, transitionDuration);
} catch (error) {
console.error("Error closing notification:", error);
}
};
<div
aria-live="assertive"
class="pointer-events-none fixed inset-x-4 bottom-6 flex flex-col items-center space-y-4 sm:inset-x-6 sm:bottom-auto sm:top-6 sm:items-end"
>
<div
class="notification pointer-events-auto relative flex w-full max-w-sm items-start gap-x-3 rounded-xl bg-white p-4 shadow-lg ring-1 ring-inset ring-gray-200 transition-opacity"
>
<div class="flex flex-1 flex-col gap-4 sm:flex-row">
<div class="shrink-0">
<svg
aria-hidden="true"
class="size-5 text-green-500"
viewBox="0 0 55 56"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M43.8919 18.4573C45.1123 19.6777 45.1123 21.6563 43.8919 22.8767L25.9716 40.797C24.7513 42.0173 22.7727 42.0173 21.5523 40.797L13.5257 32.771C12.3053 31.5507 12.3052 29.572 13.5256 28.3516C14.7459 27.1312 16.7245 27.1311 17.945 28.3515L23.7618 34.1679L39.4725 18.4573C40.6929 17.2369 42.6715 17.2369 43.8919 18.4573Z"
fill="currentColor"
></path>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M27.5 5.66699C15.0736 5.66699 5 15.7406 5 28.167C5 40.5934 15.0736 50.667 27.5 50.667C39.9264 50.667 50 40.5934 50 28.167C50 15.7406 39.9264 5.66699 27.5 5.66699ZM0 28.167C0 12.9792 12.3122 0.666992 27.5 0.666992C42.6878 0.666992 55 12.9792 55 28.167C55 43.3548 42.6878 55.667 27.5 55.667C12.3122 55.667 0 43.3548 0 28.167Z"
fill="currentColor"
></path>
</svg>
</div>
<div class="flex-1">
<p class="text-sm font-semibold text-gray-900">
Successfully saved!
</p>
<p class="mt-1 text-sm text-gray-500">
You can view the updated information on the dashboard.
</p>
</div>
</div>
<div
class="absolute right-4 top-4 shrink-0 sm:static sm:right-auto sm:top-auto"
>
<button
type="button"
class="close relative rounded-md text-gray-400 hover:text-gray-500 focus:outline-2 focus:outline-offset-2 focus:outline-pink-500"
>
<span class="sr-only">Close</span>
<svg
aria-hidden="true"
class="size-5"
viewBox="0 0 60 60"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.573 41.6601C14.809 42.4242 14.809 43.6628 15.573 44.4269C16.3371 45.191 17.5759 45.191 18.34 44.4269L15.573 41.6601ZM31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166L31.3834 31.3834ZM28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834L28.6166 28.6166ZM44.4269 18.34C45.191 17.5759 45.191 16.3371 44.4269 15.573C43.6628 14.809 42.4242 14.809 41.6601 15.573L44.4269 18.34ZM31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834L31.3834 28.6166ZM41.6601 44.4269C42.4242 45.191 43.6628 45.191 44.4269 44.4269C45.191 43.6628 45.191 42.4242 44.4269 41.6601L41.6601 44.4269ZM28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166L28.6166 31.3834ZM18.34 15.573C17.5759 14.809 16.3371 14.809 15.573 15.573C14.809 16.3371 14.809 17.5759 15.573 18.34L18.34 15.573ZM18.34 44.4269L31.3834 31.3834L28.6166 28.6166L15.573 41.6601L18.34 44.4269ZM31.3834 31.3834L44.4269 18.34L41.6601 15.573L28.6166 28.6166L31.3834 31.3834ZM28.6166 31.3834L41.6601 44.4269L44.4269 41.6601L31.3834 28.6166L28.6166 31.3834ZM31.3834 28.6166L18.34 15.573L15.573 18.34L28.6166 31.3834L31.3834 28.6166Z"
fill="currentColor"
></path>
</svg>
<span class="absolute -inset-0.5 rounded-md"></span>
</button>
</div>
</div>
</div>
// Handle click events using event delegation
document.addEventListener("click", (event) => {
const button = event.target.closest("button");
if (button?.classList.contains("close")) {
closeBtnHandler(button);
}
});
const closeBtnHandler = (button) => {
try {
// Find the closest notification element
const notification = button.closest(".notification");
if (!notification) return;
// Add fade-out effect
notification.classList.add("opacity-0");
// Remove the notification after the transition
const transitionDuration =
parseFloat(getComputedStyle(notification).transitionDuration) *
1000 || 150;
setTimeout(() => {
notification.remove();
}, transitionDuration);
} catch (error) {
console.error("Error closing notification:", error);
}
};
<div
aria-live="assertive"
class="pointer-events-none fixed inset-x-4 bottom-6 flex flex-col items-center space-y-4 sm:inset-x-6 sm:bottom-auto sm:top-6 sm:items-end"
>
<div
class="notification pointer-events-auto relative flex w-full max-w-sm items-start gap-x-3 rounded-xl bg-white p-4 shadow-lg ring-1 ring-inset ring-gray-200 transition-opacity"
>
<div class="flex flex-1 flex-col gap-4 sm:flex-row">
<div class="shrink-0">
<div
class="flex size-10 items-center justify-center rounded-lg shadow-sm ring-1 ring-inset ring-gray-200"
>
<svg
aria-hidden="true"
class="size-5 text-gray-700"
viewBox="0 0 40 40"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M25.5557 11.6853C23.9112 10.5865 21.9778 10 20 10V0C23.9556 0 27.8224 1.17298 31.1114 3.37061C34.4004 5.56823 36.9638 8.69181 38.4776 12.3463C39.9913 16.0008 40.3874 20.0222 39.6157 23.9018C38.844 27.7814 36.9392 31.3451 34.1421 34.1421C31.3451 36.9392 27.7814 38.844 23.9018 39.6157C20.0222 40.3874 16.0008 39.9913 12.3463 38.4776C8.69181 36.9638 5.56823 34.4004 3.37061 31.1114C1.17298 27.8224 0 23.9556 0 20H10C10 21.9778 10.5865 23.9112 11.6853 25.5557C12.7841 27.2002 14.3459 28.4819 16.1732 29.2388C18.0004 29.9957 20.0111 30.1937 21.9509 29.8078C23.8907 29.422 25.6725 28.4696 27.0711 27.0711C28.4696 25.6725 29.422 23.8907 29.8078 21.9509C30.1937 20.0111 29.9957 18.0004 29.2388 16.1732C28.4819 14.3459 27.2002 12.7841 25.5557 11.6853Z"
fill="currentColor"
></path>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M10 5.16562e-07C10 1.31322 9.74135 2.61358 9.2388 3.82683C8.73625 5.04009 7.99966 6.14248 7.07107 7.07107C6.14249 7.99966 5.0401 8.73625 3.82684 9.2388C2.61358 9.74134 1.31322 10 5.4439e-06 10L5.00679e-06 20C2.62644 20 5.22716 19.4827 7.65368 18.4776C10.0802 17.4725 12.285 15.9993 14.1421 14.1421C15.9993 12.285 17.4725 10.0802 18.4776 7.65367C19.4827 5.22715 20 2.62643 20 -3.81469e-06L10 5.16562e-07Z"
fill="currentColor"
></path>
</svg>
</div>
</div>
<div class="flex-1">
<p class="text-sm font-semibold text-gray-900">
Version 2.1.0 is available!
</p>
<p class="mt-1 text-sm text-gray-500">
Many new features added and bugs fixed. Update now!
</p>
<div class="mt-3 flex gap-x-3">
<button
type="button"
class="relative text-sm font-semibold text-pink-500 hover:text-pink-400"
>
Changelog
<span class="absolute -inset-1"></span>
</button>
<button
type="button"
class="relative text-sm font-semibold text-gray-700 hover:text-gray-500"
>
Dismiss
<span class="absolute -inset-1"></span>
</button>
</div>
</div>
</div>
<div
class="absolute right-4 top-4 shrink-0 sm:static sm:right-auto sm:top-auto"
>
<button
type="button"
class="close relative rounded-md text-gray-400 hover:text-gray-500 focus:outline-2 focus:outline-offset-2 focus:outline-pink-500"
>
<span class="sr-only">Close</span>
<svg
aria-hidden="true"
class="size-5"
viewBox="0 0 60 60"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.573 41.6601C14.809 42.4242 14.809 43.6628 15.573 44.4269C16.3371 45.191 17.5759 45.191 18.34 44.4269L15.573 41.6601ZM31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166L31.3834 31.3834ZM28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834L28.6166 28.6166ZM44.4269 18.34C45.191 17.5759 45.191 16.3371 44.4269 15.573C43.6628 14.809 42.4242 14.809 41.6601 15.573L44.4269 18.34ZM31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834L31.3834 28.6166ZM41.6601 44.4269C42.4242 45.191 43.6628 45.191 44.4269 44.4269C45.191 43.6628 45.191 42.4242 44.4269 41.6601L41.6601 44.4269ZM28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166L28.6166 31.3834ZM18.34 15.573C17.5759 14.809 16.3371 14.809 15.573 15.573C14.809 16.3371 14.809 17.5759 15.573 18.34L18.34 15.573ZM18.34 44.4269L31.3834 31.3834L28.6166 28.6166L15.573 41.6601L18.34 44.4269ZM31.3834 31.3834L44.4269 18.34L41.6601 15.573L28.6166 28.6166L31.3834 31.3834ZM28.6166 31.3834L41.6601 44.4269L44.4269 41.6601L31.3834 28.6166L28.6166 31.3834ZM31.3834 28.6166L18.34 15.573L15.573 18.34L28.6166 31.3834L31.3834 28.6166Z"
fill="currentColor"
></path>
</svg>
<span class="absolute -inset-0.5 rounded-md"></span>
</button>
</div>
</div>
</div>
// Handle click events using event delegation
document.addEventListener("click", (event) => {
const button = event.target.closest("button");
if (button?.classList.contains("close")) {
closeBtnHandler(button);
}
});
const closeBtnHandler = (button) => {
try {
// Find the closest notification element
const notification = button.closest(".notification");
if (!notification) return;
// Add fade-out effect
notification.classList.add("opacity-0");
// Remove the notification after the transition
const transitionDuration =
parseFloat(getComputedStyle(notification).transitionDuration) *
1000 || 150;
setTimeout(() => {
notification.remove();
}, transitionDuration);
} catch (error) {
console.error("Error closing notification:", error);
}
};
<div
aria-live="assertive"
class="pointer-events-none fixed inset-x-4 bottom-6 flex flex-col items-center space-y-4 sm:inset-x-6 sm:bottom-auto sm:top-6 sm:items-end"
>
<div
class="notification pointer-events-auto relative flex w-full max-w-sm items-start gap-x-3 rounded-xl bg-white p-4 shadow-lg ring-1 ring-inset ring-gray-200 transition-opacity"
>
<div class="flex flex-1 flex-col items-start gap-4 sm:flex-row">
<div class="shrink-0">
<div class="relative rounded-full">
<span
aria-hidden="true"
class="absolute inset-0 h-10 w-10 rounded-full ring-1 ring-inset ring-gray-900/10"
></span>
<img
class="h-10 w-10 rounded-full object-cover"
src="https://images.unsplash.com/photo-1580489944761-15a19d654956?q=80&w=256&h=256&auto=format&fit=facearea&facepad=2&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt=""
/>
<span
aria-hidden="true"
class="absolute bottom-0 right-0 h-2.5 w-2.5 rounded-full bg-green-400 ring-2 ring-white"
></span>
</div>
</div>
<div class="flex-1">
<div class="flex gap-x-2">
<p class="text-sm font-semibold text-gray-900">Lila Bennett</p>
<p class="text-sm text-gray-400">3 mins ago</p>
</div>
<p class="mt-1 text-sm text-gray-500">
Loved the new design, great work! 👏
</p>
<div class="mt-3 flex gap-x-3">
<button
type="button"
class="relative text-sm font-semibold text-pink-500 hover:text-pink-400"
>
Reply
<span class="absolute -inset-1"></span>
</button>
<button
type="button"
class="relative text-sm font-semibold text-gray-700 hover:text-gray-500"
>
Dismiss
<span class="absolute -inset-1"></span>
</button>
</div>
</div>
</div>
<div
class="absolute right-4 top-4 shrink-0 sm:static sm:right-auto sm:top-auto"
>
<button
type="button"
class="close relative rounded-md text-gray-400 hover:text-gray-500 focus:outline-2 focus:outline-offset-2 focus:outline-pink-500"
>
<span class="sr-only">Close</span>
<svg
aria-hidden="true"
class="size-5"
viewBox="0 0 60 60"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.573 41.6601C14.809 42.4242 14.809 43.6628 15.573 44.4269C16.3371 45.191 17.5759 45.191 18.34 44.4269L15.573 41.6601ZM31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166L31.3834 31.3834ZM28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834L28.6166 28.6166ZM44.4269 18.34C45.191 17.5759 45.191 16.3371 44.4269 15.573C43.6628 14.809 42.4242 14.809 41.6601 15.573L44.4269 18.34ZM31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834L31.3834 28.6166ZM41.6601 44.4269C42.4242 45.191 43.6628 45.191 44.4269 44.4269C45.191 43.6628 45.191 42.4242 44.4269 41.6601L41.6601 44.4269ZM28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166L28.6166 31.3834ZM18.34 15.573C17.5759 14.809 16.3371 14.809 15.573 15.573C14.809 16.3371 14.809 17.5759 15.573 18.34L18.34 15.573ZM18.34 44.4269L31.3834 31.3834L28.6166 28.6166L15.573 41.6601L18.34 44.4269ZM31.3834 31.3834L44.4269 18.34L41.6601 15.573L28.6166 28.6166L31.3834 31.3834ZM28.6166 31.3834L41.6601 44.4269L44.4269 41.6601L31.3834 28.6166L28.6166 31.3834ZM31.3834 28.6166L18.34 15.573L15.573 18.34L28.6166 31.3834L31.3834 28.6166Z"
fill="currentColor"
></path>
</svg>
<span class="absolute -inset-0.5 rounded-md"></span>
</button>
</div>
</div>
</div>
// Handle click events using event delegation
document.addEventListener("click", (event) => {
const button = event.target.closest("button");
if (button?.classList.contains("close")) {
closeBtnHandler(button);
}
});
const closeBtnHandler = (button) => {
try {
// Find the closest notification element
const notification = button.closest(".notification");
if (!notification) return;
// Add fade-out effect
notification.classList.add("opacity-0");
// Remove the notification after the transition
const transitionDuration =
parseFloat(getComputedStyle(notification).transitionDuration) *
1000 || 150;
setTimeout(() => {
notification.remove();
}, transitionDuration);
} catch (error) {
console.error("Error closing notification:", error);
}
};
<div
aria-live="assertive"
class="pointer-events-none fixed inset-x-4 bottom-6 flex flex-col items-center space-y-4 sm:inset-x-6 sm:bottom-auto sm:top-6 sm:items-end"
>
<div
class="notification pointer-events-auto flex w-full max-w-sm overflow-hidden rounded-xl border border-gray-200 bg-white shadow-lg transition-opacity sm:max-w-lg"
>
<div class="hidden w-40 shrink-0 bg-gray-50 sm:block">
<img
class="h-full w-full object-cover"
src="https://images.unsplash.com/photo-1692090383592-5c4c47735dd4?q=80&w=2069&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt=""
/>
</div>
<div class="relative flex-1 p-4 sm:pl-5">
<div class="flex items-start gap-x-3">
<div class="flex-1">
<div class="pr-8 sm:pr-0">
<p class="text-sm font-semibold text-gray-900">
Your are invited to AI webinar
</p>
<p class="mt-1 text-sm text-gray-500">
Join us for a free webinar on AI and its applications in the
real world.
</p>
</div>
<div class="mt-4">
<div
class="h-40 w-full overflow-hidden rounded-md bg-gray-50 sm:hidden"
>
<img
class="h-full w-full object-cover"
src="https://images.unsplash.com/photo-1692090383592-5c4c47735dd4?q=80&w=2069&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D"
alt=""
/>
</div>
<div class="mt-4 flex items-center gap-x-3 sm:mt-0">
<button
type="button"
class="rounded-md bg-pink-500 px-2.5 py-1.5 text-sm font-semibold text-white shadow-sm hover:bg-pink-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-pink-500"
>
Accept
</button>
<button
type="button"
class="rounded-md bg-white px-2.5 py-1.5 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-gray-900"
>
Decline
</button>
</div>
</div>
</div>
<div
class="absolute right-4 top-4 sm:static sm:inset-auto sm:shrink-0"
>
<button
type="button"
class="close relative rounded-md text-gray-400 hover:text-gray-500 focus:outline-2 focus:outline-offset-2 focus:outline-pink-500"
>
<span class="sr-only">Close</span>
<svg
aria-hidden="true"
class="size-5"
viewBox="0 0 60 60"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M15.573 41.6601C14.809 42.4242 14.809 43.6628 15.573 44.4269C16.3371 45.191 17.5759 45.191 18.34 44.4269L15.573 41.6601ZM31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166L31.3834 31.3834ZM28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834L28.6166 28.6166ZM44.4269 18.34C45.191 17.5759 45.191 16.3371 44.4269 15.573C43.6628 14.809 42.4242 14.809 41.6601 15.573L44.4269 18.34ZM31.3834 28.6166C30.6193 27.8525 29.3807 27.8525 28.6166 28.6166C27.8525 29.3807 27.8525 30.6193 28.6166 31.3834L31.3834 28.6166ZM41.6601 44.4269C42.4242 45.191 43.6628 45.191 44.4269 44.4269C45.191 43.6628 45.191 42.4242 44.4269 41.6601L41.6601 44.4269ZM28.6166 31.3834C29.3807 32.1475 30.6193 32.1475 31.3834 31.3834C32.1475 30.6193 32.1475 29.3807 31.3834 28.6166L28.6166 31.3834ZM18.34 15.573C17.5759 14.809 16.3371 14.809 15.573 15.573C14.809 16.3371 14.809 17.5759 15.573 18.34L18.34 15.573ZM18.34 44.4269L31.3834 31.3834L28.6166 28.6166L15.573 41.6601L18.34 44.4269ZM31.3834 31.3834L44.4269 18.34L41.6601 15.573L28.6166 28.6166L31.3834 31.3834ZM28.6166 31.3834L41.6601 44.4269L44.4269 41.6601L31.3834 28.6166L28.6166 31.3834ZM31.3834 28.6166L18.34 15.573L15.573 18.34L28.6166 31.3834L31.3834 28.6166Z"
fill="currentColor"
></path>
</svg>
<span class="absolute -inset-0.5 rounded-md"></span>
</button>
</div>
</div>
</div>
</div>
</div>
// Handle click events using event delegation
document.addEventListener("click", (event) => {
const button = event.target.closest("button");
if (button?.classList.contains("close")) {
closeBtnHandler(button);
}
});
const closeBtnHandler = (button) => {
try {
// Find the closest notification element
const notification = button.closest(".notification");
if (!notification) return;
// Add fade-out effect
notification.classList.add("opacity-0");
// Remove the notification after the transition
const transitionDuration =
parseFloat(getComputedStyle(notification).transitionDuration) *
1000 || 150;
setTimeout(() => {
notification.remove();
}, transitionDuration);
} catch (error) {
console.error("Error closing notification:", error);
}
};
<div aria-live="assertive" class="pointer-events-none fixed inset-x-4 bottom-6 flex flex-col items-center space-y-4 sm:inset-x-6 sm:bottom-auto sm:top-6">
<div class="pointer-events-auto flex max-w-sm items-start gap-x-2.5 rounded-full bg-white px-4 py-2.5 shadow transition-opacity">
<div class="-ml-1.5 shrink-0">
<svg aria-hidden="true" class="size-5 text-green-500" viewBox="0 0 55 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M43.8919 18.4573C45.1123 19.6777 45.1123 21.6563 43.8919 22.8767L25.9716 40.797C24.7513 42.0173 22.7727 42.0173 21.5523 40.797L13.5257 32.771C12.3053 31.5507 12.3052 29.572 13.5256 28.3516C14.7459 27.1312 16.7245 27.1311 17.945 28.3515L23.7618 34.1679L39.4725 18.4573C40.6929 17.2369 42.6715 17.2369 43.8919 18.4573Z" fill="currentColor"></path>
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.5 5.66699C15.0736 5.66699 5 15.7406 5 28.167C5 40.5934 15.0736 50.667 27.5 50.667C39.9264 50.667 50 40.5934 50 28.167C50 15.7406 39.9264 5.66699 27.5 5.66699ZM0 28.167C0 12.9792 12.3122 0.666992 27.5 0.666992C42.6878 0.666992 55 12.9792 55 28.167C55 43.3548 42.6878 55.667 27.5 55.667C12.3122 55.667 0 43.3548 0 28.167Z" fill="currentColor"></path>
</svg>
</div>
<p class="text-sm text-gray-700">Message sent!</p>
</div>
</div>
Frequently asked questions
-
Floating toast messages in success, error, warning, and info styles, some with an icon and action button, and notification panel/dropdown layouts for listing multiple items.
-
The dismiss button on notification components uses vanilla JavaScript that's already included in the component. For showing and hiding them on a trigger, that part is yours to wire up however fits your setup.
-
The toast variants use fixed positioning in the top-right or bottom-right corner. You can adjust the top/bottom and left/right classes to put them wherever you want.
-
That requires a bit of JavaScript to manage the queue and offset positioning. The components themselves are the individual notification UI, stacking logic is on you to build.
Related Tailwind CSS components
More free, copy-paste Tailwind CSS components to use in your projects.