Open demo

CSS code

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 6.5l11 11M17.5 6.5l-11 11"/></symbol>
  <symbol id="i-wrench" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a4 4 0 0 0 5 5L21 12.6a6 6 0 0 1-7.9 2.6L7 21.3a2 2 0 0 1-2.8-2.8l6.1-6.1a6 6 0 0 1 2.6-7.9z"/></symbol>
  <symbol id="i-cookie" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a9 9 0 1 0 9 9 3 3 0 0 1-3.5-3A3 3 0 0 1 14 5.5 3 3 0 0 1 12 3z"/><path d="M8.5 9.5h.01M8 14.5h.01M12.5 16h.01M15.5 13h.01"/></symbol>
</svg>

<div><span class="lbl">Announcement bar</span>
<div class="site">
  <div class="bn bn-announce" role="region" aria-label="Announcement" data-banner>
    <p class="bn-text"><span class="bn-tag">New</span>Order ahead from the Fernhill app and skip the queue. <a href="#">Get the app</a></p>
    <button class="bn-close" type="button" aria-label="Dismiss announcement" data-dismiss><svg aria-hidden="true"><use href="#i-x"/></svg></button>
  </div>
  <div aria-hidden="true"><div class="site-nav"><span class="site-logo"><i></i>Fernhill Coffee</span><span class="site-links"><i></i><i></i><i></i></span></div>
  <div class="site-body"><div><i class="h"></i><i class="l" style="width:92%"></i><i class="l" style="width:76%"></i><i class="l" style="width:84%"></i></div><i class="pic"></i></div></div>
</div></div>

<div><span class="lbl">Maintenance banner</span>
<div class="site">
  <div class="bn bn-maint" role="region" aria-label="Scheduled maintenance" data-banner>
    <svg class="bn-icon" aria-hidden="true"><use href="#i-wrench"/></svg>
    <p class="bn-text"><strong>Scheduled maintenance on Sunday 12 October, 02:00 to 04:00 UTC.</strong> Online ordering will be paused. <a href="#">Add to calendar</a></p>
    <button class="bn-close" type="button" aria-label="Dismiss maintenance notice" data-dismiss><svg aria-hidden="true"><use href="#i-x"/></svg></button>
  </div>
  <div aria-hidden="true"><div class="site-nav"><span class="site-logo"><i></i>Fernhill Coffee</span><span class="site-links"><i></i><i></i><i></i></span></div>
  <div class="site-body"><div><i class="h"></i><i class="l" style="width:92%"></i><i class="l" style="width:76%"></i><i class="l" style="width:84%"></i></div><i class="pic"></i></div></div>
</div></div>

<div><span class="lbl">Cookie notice with equal choices</span>
<div class="site site-tall">
  <div aria-hidden="true"><div class="site-nav"><span class="site-logo"><i></i>Fernhill Coffee</span><span class="site-links"><i></i><i></i><i></i></span></div>
  <div class="site-body"><div><i class="h"></i><i class="l" style="width:92%"></i><i class="l" style="width:76%"></i><i class="l" style="width:84%"></i></div><i class="pic"></i></div></div>
  <section class="bn-cookie" aria-labelledby="bn-cookie-title" data-banner>
    <h2 id="bn-cookie-title"><svg aria-hidden="true"><use href="#i-cookie"/></svg>Cookies on Fernhill</h2>
    <p>We use essential cookies to run the shop. With your consent we also measure visits to improve the menu. <a href="#">Cookie settings</a></p>
    <div class="bn-choices"><button class="bn-btn" type="button" data-dismiss>Reject non-essential</button><button class="bn-btn bn-btn-dark" type="button" data-dismiss>Accept all</button></div>
  </section>
</div></div>
CSS
.bn{display:flex;align-items:center;gap:12px;font-size:.9375rem;line-height:1.5}
.bn-text{flex:1;min-width:0;margin:0}
.bn a{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:3px;border-radius:3px}
.bn a:hover{text-decoration-thickness:2px}
.bn-close{flex:none;display:grid;place-items:center;width:32px;height:32px;padding:0;border:0;border-radius:8px;background:transparent;color:inherit;cursor:pointer;
  transition:background-color .15s}
.bn-close svg{width:16px;height:16px}
.bn a:focus-visible,.bn-close:focus-visible{outline:2px solid currentColor;outline-offset:2px}
.bn-icon{flex:none;width:20px;height:20px}

/* 1. Announcement bar: first thing in <body>, above the header */
.bn-announce{padding:10px 12px 10px 20px;background:linear-gradient(90deg,#312e81,#5b21b6 55%,#6d28d9);color:#fff;text-align:center}
.bn-announce .bn-text{padding-left:32px}
.bn-tag{display:inline-block;margin-right:8px;padding:1px 9px;border-radius:99px;background:rgba(255,255,255,.18);font-size:.75rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;vertical-align:1px}
.bn-announce .bn-close:hover{background:rgba(255,255,255,.16)}

/* 2. Maintenance banner: striped top edge, calendar link */
.bn-maint{position:relative;padding:14px 12px 14px 20px;background:#fffbeb;color:#78350f;border-bottom:1px solid #fde68a}
.bn-maint::before{content:"";position:absolute;inset:0 0 auto;height:5px;background:repeating-linear-gradient(-45deg,#f59e0b 0 10px,#1f2937 10px 20px)}
.bn-maint .bn-icon{color:#b45309}
.bn-maint strong{color:#451a03}
.bn-maint .bn-close:hover{background:rgba(120,53,15,.1)}

/* 3. Cookie notice: fixed to the bottom corner, equal-weight choices */
.bn-cookie{position:fixed;left:16px;bottom:16px;z-index:50;display:block;width:min(400px,calc(100% - 32px));padding:20px;background:#fff;color:#334155;
  border:1px solid #e2e8f0;border-radius:16px;box-shadow:0 24px 48px -16px rgba(15,23,42,.35)}
.bn-cookie h2{display:flex;align-items:center;gap:8px;margin:0 0 6px;font-size:1rem;color:#0f172a}
.bn-cookie h2 svg{width:22px;height:22px;color:#b45309}
.bn-cookie p{margin:0;font-size:.875rem}
.bn-cookie a{color:#0f172a}
.bn-cookie a:focus-visible{outline-color:#0f172a}
.bn-choices{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}
.bn-btn{height:40px;padding:0 12px;border:1px solid #0f172a;border-radius:10px;background:#fff;color:#0f172a;font:inherit;font-size:.875rem;font-weight:600;cursor:pointer;transition:background-color .15s}
.bn-btn:hover{background:#f1f5f9}
.bn-btn-dark{background:#0f172a;color:#fff}
.bn-btn-dark:hover{background:#1e293b}
.bn-btn:focus-visible{outline:2px solid #0f172a;outline-offset:2px}

@media (max-width:640px){.bn-announce{text-align:left;padding-left:16px}.bn-announce .bn-text{padding-left:0}.bn-maint{padding-left:16px}}
@media (max-width:400px){.bn-choices{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){.bn-close,.bn-btn{transition:none}}
JavaScript
// Dismiss a banner, then move focus to the next focusable element after it so keyboard users keep their place.
// To keep a banner closed across visits, save its id to localStorage here and skip it on load.
document.addEventListener('click', function (e) {
  var btn = e.target.closest('[data-dismiss]');
  if (!btn) return;
  var banner = btn.closest('[data-banner]');
  if (!banner) return;
  var focusables = document.querySelectorAll('a[href], button:not([disabled]), input, select, textarea, [tabindex]:not([tabindex="-1"])');
  var next = Array.prototype.find.call(focusables, function (el) {
    return !banner.contains(el) && (banner.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING);
  });
  var done = function () { banner.remove(); if (next) next.focus(); };
  if (!banner.animate || matchMedia('(prefers-reduced-motion: reduce)').matches) return done();
  banner.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 160, easing: 'ease-in' }).onfinish = done;
});

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS, Bootstrap 5.3.8 JS bundle

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-wrench" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a4 4 0 0 0 5 5L21 12.6a6 6 0 0 1-7.9 2.6L7 21.3a2 2 0 0 1-2.8-2.8l6.1-6.1a6 6 0 0 1 2.6-7.9z"/></symbol>
  <symbol id="i-cookie" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a9 9 0 1 0 9 9 3 3 0 0 1-3.5-3A3 3 0 0 1 14 5.5 3 3 0 0 1 12 3z"/><path d="M8.5 9.5h.01M8 14.5h.01M12.5 16h.01M15.5 13h.01"/></symbol>
</svg>

<div><span class="lbl">Announcement bar</span>
<div class="site">
  <div class="alert bn bn-announce fade show" role="region" aria-label="Announcement">
    <p><span class="badge rounded-pill">New</span>Order ahead from the Fernhill app and skip the queue. <a href="#" class="alert-link">Get the app</a></p>
    <button type="button" class="btn-close btn-close-white" data-bs-dismiss="alert" aria-label="Dismiss announcement"></button>
  </div>
  <div aria-hidden="true"><div class="site-nav"><span class="site-logo"><i></i>Fernhill Coffee</span><span class="site-links"><i></i><i></i><i></i></span></div>
  <div class="site-body"><div><i class="h"></i><i class="l" style="width:92%"></i><i class="l" style="width:76%"></i><i class="l" style="width:84%"></i></div><i class="pic"></i></div></div>
</div></div>

<div><span class="lbl">Maintenance banner</span>
<div class="site">
  <div class="alert bn bn-maint fade show" role="region" aria-label="Scheduled maintenance">
    <svg class="bn-icon" aria-hidden="true"><use href="#i-wrench"/></svg>
    <p><strong>Scheduled maintenance on Sunday 12 October, 02:00 to 04:00 UTC.</strong> Online ordering will be paused. <a href="#" class="alert-link">Add to calendar</a></p>
    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Dismiss maintenance notice"></button>
  </div>
  <div aria-hidden="true"><div class="site-nav"><span class="site-logo"><i></i>Fernhill Coffee</span><span class="site-links"><i></i><i></i><i></i></span></div>
  <div class="site-body"><div><i class="h"></i><i class="l" style="width:92%"></i><i class="l" style="width:76%"></i><i class="l" style="width:84%"></i></div><i class="pic"></i></div></div>
</div></div>

<div><span class="lbl">Cookie notice with equal choices</span>
<div class="site site-tall">
  <div aria-hidden="true"><div class="site-nav"><span class="site-logo"><i></i>Fernhill Coffee</span><span class="site-links"><i></i><i></i><i></i></span></div>
  <div class="site-body"><div><i class="h"></i><i class="l" style="width:92%"></i><i class="l" style="width:76%"></i><i class="l" style="width:84%"></i></div><i class="pic"></i></div></div>
  <section class="card bn-cookie fade show" id="cookie-notice" aria-labelledby="bn-cookie-title"><div class="card-body">
    <h2 class="card-title" id="bn-cookie-title"><svg aria-hidden="true"><use href="#i-cookie"/></svg>Cookies on Fernhill</h2>
    <p class="card-text">We use essential cookies to run the shop. With your consent we also measure visits to improve the menu. <a href="#">Cookie settings</a></p>
    <div class="bn-choices"><button class="btn btn-outline-dark" type="button" data-bs-dismiss="alert" data-bs-target="#cookie-notice">Reject non-essential</button><button class="btn btn-dark" type="button" data-bs-dismiss="alert" data-bs-target="#cookie-notice">Accept all</button></div>
  </div></section>
</div></div>
CSS
/* Banners are Bootstrap .alert elements closed by the Alert plugin (data-bs-dismiss="alert"). The cookie notice is a .card closed the same way. */
.bn{--bs-alert-margin-bottom:0;--bs-alert-border-radius:0;--bs-alert-padding-y:10px;display:flex;align-items:center;gap:12px;border:0;font-size:.9375rem;line-height:1.5}
.bn p{flex:1;min-width:0;margin:0}
.bn .alert-link{color:inherit;font-weight:600;text-decoration:underline;text-underline-offset:3px;border-radius:3px}
.bn .alert-link:hover{text-decoration-thickness:2px}
.bn .alert-link:focus-visible{outline:2px solid currentColor;outline-offset:2px}
.bn .btn-close{--bs-btn-close-opacity:.85;--bs-btn-close-hover-opacity:1;--bs-btn-close-focus-opacity:1;--bs-btn-close-focus-shadow:0 0 0 2px currentColor;
  flex:none;width:32px;height:32px;padding:0;border-radius:8px;background-size:11px}
.bn-icon{flex:none;width:20px;height:20px}

/* 1. Announcement bar */
.bn-announce{--bs-alert-padding-x:20px;padding-right:12px;background:linear-gradient(90deg,#312e81,#5b21b6 55%,#6d28d9);color:#fff;text-align:center}
.bn-announce p{padding-left:32px}
.bn-announce .badge{margin-right:8px;padding:3px 9px;background:rgba(255,255,255,.18);font-size:.75rem;letter-spacing:.04em;text-transform:uppercase;vertical-align:1px}
.bn-announce .btn-close:hover{background-color:rgba(255,255,255,.16)}
.bn-announce .btn-close:focus-visible{box-shadow:0 0 0 2px #fff}

/* 2. Maintenance banner */
.bn-maint{--bs-alert-padding-x:20px;--bs-alert-padding-y:14px;padding-right:12px;position:relative;background:#fffbeb;color:#78350f;border-bottom:1px solid #fde68a}
.bn-maint::before{content:"";position:absolute;inset:0 0 auto;height:5px;background:repeating-linear-gradient(-45deg,#f59e0b 0 10px,#1f2937 10px 20px)}
.bn-maint .bn-icon{color:#b45309}
.bn-maint strong{color:#451a03}
.bn-maint .btn-close{--bs-btn-close-color:#78350f}
.bn-maint .btn-close:hover{background-color:rgba(120,53,15,.1)}
.bn-maint .btn-close:focus-visible{box-shadow:0 0 0 2px #78350f}

/* 3. Cookie notice */
.bn-cookie{--bs-card-spacer-x:20px;--bs-card-spacer-y:20px;--bs-card-border-color:#e2e8f0;--bs-card-border-radius:16px;--bs-card-color:#334155;
  position:fixed;left:16px;bottom:16px;z-index:1050;width:min(400px,calc(100% - 32px));box-shadow:0 24px 48px -16px rgba(15,23,42,.35)}
.bn-cookie .card-title{display:flex;align-items:center;gap:8px;margin:0 0 6px;font-size:1rem;font-weight:700;color:#0f172a}
.bn-cookie .card-title svg{width:22px;height:22px;color:#b45309}
.bn-cookie .card-text{font-size:.875rem}
.bn-cookie a{color:#0f172a;font-weight:600;text-underline-offset:3px;border-radius:3px}
.bn-cookie a:focus-visible{outline:2px solid #0f172a;outline-offset:2px}
.bn-choices{display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-top:16px}
.bn-choices .btn{--bs-btn-font-size:.875rem;--bs-btn-font-weight:600;--bs-btn-border-radius:10px;--bs-btn-focus-box-shadow:0 0 0 2px #fff,0 0 0 4px #0f172a;height:40px}
.bn-choices .btn-outline-dark{--bs-btn-color:#0f172a;--bs-btn-border-color:#0f172a;--bs-btn-hover-bg:#f1f5f9;--bs-btn-hover-color:#0f172a;--bs-btn-hover-border-color:#0f172a;--bs-btn-active-bg:#e2e8f0;--bs-btn-active-color:#0f172a}
.bn-choices .btn-dark{--bs-btn-bg:#0f172a;--bs-btn-border-color:#0f172a;--bs-btn-hover-bg:#1e293b;--bs-btn-hover-border-color:#1e293b}

@media (max-width:640px){.bn-announce{--bs-alert-padding-x:16px;text-align:left}.bn-announce p{padding-left:0}.bn-maint{--bs-alert-padding-x:16px}}
@media (max-width:400px){.bn-choices{grid-template-columns:1fr}}
@media (prefers-reduced-motion:reduce){.bn.fade,.bn-cookie.fade{transition:none}}
JavaScript
// After Bootstrap removes a banner, move focus to the next focusable element after it so keyboard users keep their place.
// To keep a banner closed across visits, save its id to localStorage in the close handler and skip it on load.
document.querySelectorAll('.bn, .bn-cookie').forEach(function (banner) {
  var next = null;
  banner.addEventListener('close.bs.alert', function () {
    var focusables = document.querySelectorAll('a[href], button:not([disabled]), input, select, textarea, [tabindex]:not([tabindex="-1"])');
    next = Array.prototype.find.call(focusables, function (el) {
      return !banner.contains(el) && (banner.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING);
    });
  });
  banner.addEventListener('closed.bs.alert', function () { if (next) next.focus(); });
});

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<svg width="0" height="0" style="position:absolute" aria-hidden="true" focusable="false">
  <symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6.5 6.5l11 11M17.5 6.5l-11 11"/></symbol>
  <symbol id="i-wrench" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.7 6.3a4 4 0 0 0 5 5L21 12.6a6 6 0 0 1-7.9 2.6L7 21.3a2 2 0 0 1-2.8-2.8l6.1-6.1a6 6 0 0 1 2.6-7.9z"/></symbol>
  <symbol id="i-cookie" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a9 9 0 1 0 9 9 3 3 0 0 1-3.5-3A3 3 0 0 1 14 5.5 3 3 0 0 1 12 3z"/><path d="M8.5 9.5h.01M8 14.5h.01M12.5 16h.01M15.5 13h.01"/></symbol>
</svg>

<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5b6474] uppercase">Announcement bar</span>
<div class="site relative overflow-hidden rounded-2xl border border-[#d6dce5] bg-white shadow-[0_1px_2px_rgba(15,23,42,.05),0_18px_40px_-22px_rgba(15,23,42,.28)]">
  <div class="flex items-center gap-3 bg-[linear-gradient(90deg,#312e81,#5b21b6_55%,#6d28d9)] py-2.5 pr-3 pl-5 text-center text-[.9375rem] text-white max-[640px]:pl-4 max-[640px]:text-left" role="region" aria-label="Announcement" data-banner>
    <p class="min-w-0 flex-1 pl-8 max-[640px]:pl-0"><span class="mr-2 inline-block rounded-full bg-white/18 px-[9px] py-px align-[1px] text-xs font-bold tracking-[.04em] uppercase">New</span>Order ahead from the Fernhill app and skip the queue. <a href="#" class="rounded-[3px] font-semibold underline underline-offset-3 hover:decoration-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current">Get the app</a></p>
    <button class="grid size-8 flex-none cursor-pointer place-items-center rounded-lg transition-colors duration-150 hover:bg-white/16 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current motion-reduce:transition-none" type="button" aria-label="Dismiss announcement" data-dismiss><svg class="size-4" aria-hidden="true"><use href="#i-x"/></svg></button>
  </div>
  <div aria-hidden="true"><div class="flex items-center gap-[22px] border-b border-[#eef1f5] px-6 py-4"><span class="flex items-center gap-[9px] font-bold text-[#0f172a]"><i class="size-[26px] rounded-lg bg-[linear-gradient(135deg,#a16207,#ea580c)]"></i>Fernhill Coffee</span><span class="ml-auto flex gap-4 max-[640px]:hidden"><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i></span></div>
  <div class="grid grid-cols-[1.2fr_1fr] gap-7 px-6 pt-[30px] pb-[34px] max-[640px]:grid-cols-1"><div><i class="mb-3 block h-[22px] w-[82%] rounded-full bg-[#dfe4ec]"></i><i class="mt-[9px] block h-[9px] w-[92%] rounded-full bg-[#e7ebf1]"></i><i class="mt-[9px] block h-[9px] w-[76%] rounded-full bg-[#e7ebf1]"></i><i class="mt-[9px] block h-[9px] w-[84%] rounded-full bg-[#e7ebf1]"></i></div><i class="block h-[150px] rounded-xl bg-[linear-gradient(135deg,#fde7c8,#f6c79a)] max-[640px]:h-[90px]"></i></div></div>
</div></div>

<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5b6474] uppercase">Maintenance banner</span>
<div class="site relative overflow-hidden rounded-2xl border border-[#d6dce5] bg-white shadow-[0_1px_2px_rgba(15,23,42,.05),0_18px_40px_-22px_rgba(15,23,42,.28)]">
  <div class="relative flex items-center gap-3 border-b border-[#fde68a] bg-[#fffbeb] py-3.5 pr-3 pl-5 text-[.9375rem] text-[#78350f] before:absolute before:inset-x-0 before:top-0 before:h-[5px] before:bg-[repeating-linear-gradient(-45deg,#f59e0b_0_10px,#1f2937_10px_20px)] max-[640px]:pl-4" role="region" aria-label="Scheduled maintenance" data-banner>
    <svg class="size-5 flex-none text-[#b45309]" aria-hidden="true"><use href="#i-wrench"/></svg>
    <p class="min-w-0 flex-1"><strong class="text-[#451a03]">Scheduled maintenance on Sunday 12 October, 02:00 to 04:00 UTC.</strong> Online ordering will be paused. <a href="#" class="rounded-[3px] font-semibold underline underline-offset-3 hover:decoration-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current">Add to calendar</a></p>
    <button class="grid size-8 flex-none cursor-pointer place-items-center rounded-lg transition-colors duration-150 hover:bg-[rgba(120,53,15,.1)] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-current motion-reduce:transition-none" type="button" aria-label="Dismiss maintenance notice" data-dismiss><svg class="size-4" aria-hidden="true"><use href="#i-x"/></svg></button>
  </div>
  <div aria-hidden="true"><div class="flex items-center gap-[22px] border-b border-[#eef1f5] px-6 py-4"><span class="flex items-center gap-[9px] font-bold text-[#0f172a]"><i class="size-[26px] rounded-lg bg-[linear-gradient(135deg,#a16207,#ea580c)]"></i>Fernhill Coffee</span><span class="ml-auto flex gap-4 max-[640px]:hidden"><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i></span></div>
  <div class="grid grid-cols-[1.2fr_1fr] gap-7 px-6 pt-[30px] pb-[34px] max-[640px]:grid-cols-1"><div><i class="mb-3 block h-[22px] w-[82%] rounded-full bg-[#dfe4ec]"></i><i class="mt-[9px] block h-[9px] w-[92%] rounded-full bg-[#e7ebf1]"></i><i class="mt-[9px] block h-[9px] w-[76%] rounded-full bg-[#e7ebf1]"></i><i class="mt-[9px] block h-[9px] w-[84%] rounded-full bg-[#e7ebf1]"></i></div><i class="block h-[150px] rounded-xl bg-[linear-gradient(135deg,#fde7c8,#f6c79a)] max-[640px]:h-[90px]"></i></div></div>
</div></div>

<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5b6474] uppercase">Cookie notice with equal choices</span>
<div class="site relative min-h-[380px] overflow-hidden rounded-2xl border border-[#d6dce5] bg-white shadow-[0_1px_2px_rgba(15,23,42,.05),0_18px_40px_-22px_rgba(15,23,42,.28)]">
  <div aria-hidden="true"><div class="flex items-center gap-[22px] border-b border-[#eef1f5] px-6 py-4"><span class="flex items-center gap-[9px] font-bold text-[#0f172a]"><i class="size-[26px] rounded-lg bg-[linear-gradient(135deg,#a16207,#ea580c)]"></i>Fernhill Coffee</span><span class="ml-auto flex gap-4 max-[640px]:hidden"><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i><i class="block h-[9px] w-[54px] rounded-full bg-[#e7ebf1]"></i></span></div>
  <div class="grid grid-cols-[1.2fr_1fr] gap-7 px-6 pt-[30px] pb-[34px] max-[640px]:grid-cols-1"><div><i class="mb-3 block h-[22px] w-[82%] rounded-full bg-[#dfe4ec]"></i><i class="mt-[9px] block h-[9px] w-[92%] rounded-full bg-[#e7ebf1]"></i><i class="mt-[9px] block h-[9px] w-[76%] rounded-full bg-[#e7ebf1]"></i><i class="mt-[9px] block h-[9px] w-[84%] rounded-full bg-[#e7ebf1]"></i></div><i class="block h-[150px] rounded-xl bg-[linear-gradient(135deg,#fde7c8,#f6c79a)] max-[640px]:h-[90px]"></i></div></div>
  <section class="fixed bottom-4 left-4 z-50 w-[min(400px,calc(100%-32px))] rounded-2xl border border-[#e2e8f0] bg-white p-5 text-[#334155] shadow-[0_24px_48px_-16px_rgba(15,23,42,.35)]" aria-labelledby="bn-cookie-title" data-banner data-cookie>
    <h2 id="bn-cookie-title" class="mb-1.5 flex items-center gap-2 text-base font-bold text-[#0f172a]"><svg class="size-[22px] text-[#b45309]" aria-hidden="true"><use href="#i-cookie"/></svg>Cookies on Fernhill</h2>
    <p class="text-sm">We use essential cookies to run the shop. With your consent we also measure visits to improve the menu. <a href="#" class="rounded-[3px] font-semibold text-[#0f172a] underline underline-offset-3 hover:decoration-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a]">Cookie settings</a></p>
    <div class="mt-4 grid grid-cols-2 gap-2 max-[400px]:grid-cols-1"><button class="h-10 cursor-pointer rounded-[10px] border border-[#0f172a] bg-white px-3 text-sm font-semibold text-[#0f172a] transition-colors duration-150 hover:bg-[#f1f5f9] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] motion-reduce:transition-none" type="button" data-dismiss>Reject non-essential</button><button class="h-10 cursor-pointer rounded-[10px] border border-[#0f172a] bg-[#0f172a] px-3 text-sm font-semibold text-white transition-colors duration-150 hover:bg-[#1e293b] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#0f172a] motion-reduce:transition-none" type="button" data-dismiss>Accept all</button></div>
  </section>
</div></div>
JavaScript
// Dismiss a banner, then move focus to the next focusable element after it so keyboard users keep their place.
// To keep a banner closed across visits, save its id to localStorage here and skip it on load.
document.addEventListener('click', function (e) {
  var btn = e.target.closest('[data-dismiss]');
  if (!btn) return;
  var banner = btn.closest('[data-banner]');
  if (!banner) return;
  var focusables = document.querySelectorAll('a[href], button:not([disabled]), input, select, textarea, [tabindex]:not([tabindex="-1"])');
  var next = Array.prototype.find.call(focusables, function (el) {
    return !banner.contains(el) && (banner.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING);
  });
  var done = function () { banner.remove(); if (next) next.focus(); };
  if (!banner.animate || matchMedia('(prefers-reduced-motion: reduce)').matches) return done();
  banner.animate([{ opacity: 1 }, { opacity: 0 }], { duration: 160, easing: 'ease-in' }).onfinish = done;
});

About this set

Three banners that speak to everyone on a site, each shown at the top or corner of a small coffee shop page. The announcement bar is a violet gradient strip above the header with a New tag, one sentence, a link and a close button; it centres its text on wide screens and left-aligns it on phones. The maintenance banner has a black and amber striped top edge, a wrench icon, the date and time window in bold, what will be unavailable and an Add to calendar link. The cookie notice is a card fixed to the bottom corner with a short explanation, a Cookie settings link and two buttons of equal size and weight, Reject non-essential and Accept all, because hiding the reject option behind a smaller button is a dark pattern regulators now act on. Each banner is a labelled region, not an alert, since none of them is urgent. A short script removes a banner and moves focus to the next focusable element after it; a comment shows where to store the choice so the banner stays closed on the next visit. The Bootstrap version builds the bars from .alert and the notice from .card, closed by the Alert plugin.

What’s included

  • Announcement bar, maintenance banner and cookie notice
  • Cookie choices with equal visual weight
  • Banners are labelled regions, not alerts
  • Focus moves to the next element after a banner is closed
  • Bootstrap Alert plugin closes both .alert bars and the .card notice

Accessibility

Each banner is a region with an accessible name, such as Announcement or Scheduled maintenance, and each close button is named, such as Dismiss announcement. Links in the text are underlined, every control has a visible focus outline in the banner's own text colour, and focus moves to the next element on the page after a banner is closed. The fade on close and hover transitions are removed under prefers-reduced-motion.

Customise it

Change the gradient on .bn-announce, the stripe colours and background on .bn-maint, and the button colours on .bn-btn. The cookie notice is position:fixed with left and bottom offsets of 16px; change them to move it. In Bootstrap the same values sit on .bn-announce, .bn-maint and the --bs-card-* and --bs-btn-* variables; in Tailwind edit the utilities.