✦ A decade of Canvas craft, now driven by AI — describe it, watch it build live.Start building
Bootstrap 5Navigation

Bootstrap 5 Notification Dropdown

A notification dropdown is a navbar-integrated panel that reveals a scrollable list of user alerts, messages, or system events when a bell icon is clicked. It is composed from Bootstrap 5's Dropdown plugin, Badge utility, List Group, and Flexbox utilities — no custom component exists in the official Bootstrap distribution. Use it in admin dashboards, SaaS applications, or any authenticated interface where users need real-time or recent activity at a glance.

Primary Class

.dropdown + .dropdown-menu + .badge

Common Use Cases

  • An e-commerce admin panel shows order status changes — new orders, payment failures, and shipment updates — as individual notification items inside the dropdown.
  • A project management tool surfaces @mention alerts and task assignment notifications so team members can respond without leaving their current page.
  • A hospital staff portal displays urgent patient alerts and ward announcements with colour-coded badges distinguishing critical from informational notices.
  • A SaaS billing dashboard notifies account owners of upcoming renewal dates, failed card charges, and usage limit warnings via timestamped dropdown entries.

Variants & Classes

VariantDescription
Basic Unread BadgeBell icon button with a red badge counter and a plain dropdown list of notification items using list-group-flush inside the dropdown menu.
Grouped with Section HeadersNotification items divided into Today and Earlier sections using small muted dropdown headers, keeping recent activity visually distinct.
Scrollable Panel with Footer ActionA fixed-height scrollable list constrained with overflow-y-auto and a sticky footer link that marks all notifications as read or navigates to a full notifications page.
Inline Avatar + MetaEach notification row pairs a user avatar thumbnail with the event description and a relative timestamp, using flex utilities to align content horizontally.

Code Example

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Notification Dropdown</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
  <style>
    .notification-menu {
      width: 360px;
      max-height: 480px;
      overflow-y: auto;
    }
    .notif-dot {
      width: 8px;
      height: 8px;
      border-radius: 50%;
      flex-shrink: 0;
    }
    .list-group-item-action:focus {
      outline: 2px solid #0d6efd;
      outline-offset: -2px;
    }
  </style>
</head>
<body class="bg-light">
  <nav class="navbar navbar-expand-lg navbar-dark bg-dark px-4">
    <a class="navbar-brand" href="#">MyApp</a>
    <div class="ms-auto d-flex align-items-center gap-3">
      <!-- Notification Dropdown -->
      <div class="dropdown">
        <button
          class="btn btn-dark p-1 position-relative"
          type="button"
          id="notifDropdown"
          data-bs-toggle="dropdown"
          aria-expanded="false"
          aria-label="Notifications (4 unread)"
        >
          <i class="bi bi-bell fs-5 text-white"></i>
          <span
            class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger"
            aria-label="4 unread notifications"
          >4</span>
        </button>

        <div
          class="dropdown-menu dropdown-menu-end shadow notification-menu p-0"
          aria-labelledby="notifDropdown"
        >
          <!-- Header -->
          <div class="d-flex align-items-center justify-content-between px-3 py-2 border-bottom">
            <span class="fw-semibold">Notifications</span>
            <button class="btn btn-link btn-sm text-decoration-none p-0 text-muted" type="button">Mark all read</button>
          </div>

          <!-- Section label -->
          <p class="dropdown-header text-uppercase text-muted small mb-0 pt-2">Today</p>

          <!-- Unread item 1 -->
          <a href="#" class="list-group-item list-group-item-action d-flex align-items-start gap-3 px-3 py-2 border-0">
            <img src="https://i.pravatar.cc/36?img=12" alt="" width="36" height="36" class="rounded-circle flex-shrink-0 mt-1">
            <div class="flex-grow-1 overflow-hidden">
              <p class="mb-0 text-truncate"><strong>Sarah Connor</strong> assigned you a task in <em>Project Atlas</em>.</p>
              <small class="text-muted">2 minutes ago</small>
            </div>
            <span class="notif-dot bg-primary mt-2" aria-label="Unread"></span>
          </a>

          <!-- Unread item 2 -->
          <a href="#" class="list-group-item list-group-item-action d-flex align-items-start gap-3 px-3 py-2 border-0">
            <div class="flex-shrink-0 mt-1 d-flex align-items-center justify-content-center bg-warning-subtle rounded-circle" style="width:36px;height:36px">
              <i class="bi bi-credit-card text-warning"></i>
            </div>
            <div class="flex-grow-1 overflow-hidden">
              <p class="mb-0 text-truncate">Payment of <strong>£349.00</strong> failed — update your card details.</p>
              <small class="text-muted">15 minutes ago</small>
            </div>
            <span class="notif-dot bg-primary mt-2" aria-label="Unread"></span>
          </a>

          <!-- Unread item 3 -->
          <a href="#" class="list-group-item list-group-item-action d-flex align-items-start gap-3 px-3 py-2 border-0">
            <div class="flex-shrink-0 mt-1 d-flex align-items-center justify-content-center bg-success-subtle rounded-circle" style="width:36px;height:36px">
              <i class="bi bi-box-seam text-success"></i>
            </div>
            <div class="flex-grow-1 overflow-hidden">
              <p class="mb-0 text-truncate">Order <strong>#ORD-8821</strong> has been shipped.</p>
              <small class="text-muted">1 hour ago</small>
            </div>
            <span class="notif-dot bg-primary mt-2" aria-label="Unread"></span>
          </a>

          <!-- Section label -->
          <p class="dropdown-header text-uppercase text-muted small mb-0 pt-2">Earlier</p>

          <!-- Read item -->
          <a href="#" class="list-group-item list-group-item-action d-flex align-items-start gap-3 px-3 py-2 border-0 opacity-75">
            <img src="https://i.pravatar.cc/36?img=7" alt="" width="36" height="36" class="rounded-circle flex-shrink-0 mt-1">
            <div class="flex-grow-1 overflow-hidden">
              <p class="mb-0 text-truncate"><strong>James Briggs</strong> commented on your report.</p>
              <small class="text-muted">Yesterday, 4:52 pm</small>
            </div>
          </a>

          <!-- Read item -->
          <a href="#" class="list-group-item list-group-item-action d-flex align-items-start gap-3 px-3 py-2 border-0 opacity-75">
            <div class="flex-shrink-0 mt-1 d-flex align-items-center justify-content-center bg-danger-subtle rounded-circle" style="width:36px;height:36px">
              <i class="bi bi-exclamation-triangle text-danger"></i>
            </div>
            <div class="flex-grow-1 overflow-hidden">
              <p class="mb-0 text-truncate">Server CPU usage exceeded 90% threshold.</p>
              <small class="text-muted">2 days ago</small>
            </div>
          </a>

          <!-- Footer -->
          <div class="border-top text-center">
            <a href="/notifications" class="btn btn-link btn-sm w-100 py-2 text-decoration-none">View all notifications</a>
          </div>
        </div>
      </div>

      <!-- Profile -->
      <img src="https://i.pravatar.cc/36?img=3" alt="Profile" width="36" height="36" class="rounded-circle">
    </div>
  </nav>

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Live Examples

Minimal Bell with Badge Count

The smallest viable implementation: a bell button with a danger badge counter that toggles a plain dropdown menu. No avatars or sections — suitable for simple utility dashboards.

Example 1

Scrollable Notifications with Icon Avatars

A fixed-height scrollable list using overflow-y-auto constrained to 320 px. Each entry uses a coloured icon inside a circle as the avatar, suitable when user photos are unavailable.

Example 2

Empty State Notification Dropdown

Handles the zero-notification case gracefully with a centred icon and message inside the dropdown menu. Prevents a jarring blank panel when the user has cleared all alerts.

Example 3

Canvas Framework Variants

The Canvas template extends Bootstrap 5 with 1,658+ component variants. Generate any of these using Canvas Builder:

  • Bell icon notification dropdown with unread badge counter generated from a prompt
  • Scrollable admin notification panel with avatar rows and section headers
  • Dark navbar notification dropdown with colour-coded system alert icons
  • E-commerce order update notification dropdown with timestamped list items
  • Canvas Builder prompt: notification dropdown with mark-all-read footer action

Best Practices

Set a max-height and overflow-y on the menu

Without a constrained height, a long notification list will overflow the viewport on smaller screens. Apply a custom max-height (e.g. 400–480 px) and overflow-y: auto directly on the dropdown-menu element or a wrapper div inside it. Do not rely on Bootstrap's default dropdown sizing for this pattern.

Use aria-label and aria-live for accessibility

The trigger button should carry an aria-label that includes the unread count (e.g. 'Notifications, 4 unread') so screen-reader users know at a glance. When new notifications arrive dynamically, wrap the badge in a span with role='status' and aria-live='polite' so assistive technologies announce the updated count without interrupting the user.

Prevent dropdown close on internal clicks

If you add interactive controls inside the panel — such as a 'Mark all read' button — Bootstrap will close the dropdown on any click inside it by default. Stop this by calling event.stopPropagation() on the button's click handler, or add data-bs-auto-close='outside' to the toggle button so the menu only closes when the user clicks outside it.

Keep the badge hidden when count is zero

Use Bootstrap's d-none utility class toggled via JavaScript to hide the badge entirely when there are no unread notifications, rather than displaying a zero. A visible zero badge can cause confusion and erodes trust in the component's accuracy.

FAQ

Does Bootstrap 5 have an official notification dropdown component?
No. Bootstrap 5 ships no Notification Dropdown component. This pattern is assembled from the Dropdown plugin, Badge, List Group, and Flexbox utilities. The markup on this page is fully self-contained and does not require any third-party library beyond Bootstrap 5.3.
How do I position the badge on top of the bell icon?
Apply position-relative to the button, then position-absolute top-0 start-100 translate-middle to the badge element. This is the standard Bootstrap 5 positioned badge pattern. Adding rounded-pill ensures the badge is a pill shape regardless of digit count.
How do I stop the dropdown from closing when a user clicks inside it?
Add data-bs-auto-close='outside' to the dropdown toggle button. This tells Bootstrap's Dropdown plugin to dismiss the panel only on clicks outside the menu element, leaving internal buttons and links fully interactive without closing the dropdown prematurely.
How should I load new notifications without a page refresh?
Fetch notifications via the Fetch API or a WebSocket and update the DOM by replacing or prepending list items inside the dropdown menu. Update the badge text and toggle its d-none class based on the unread count. No special Bootstrap API is needed — the dropdown simply holds whatever HTML you inject into it.