Open demo

CSS code

HTML
<article class="notif info">
  <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg></span>
  <div class="body">
    <h2><span class="sr-only">Info: </span><a href="#">New comment on “Q3 rollout”</a></h2>
    <p>Priya replied to your thread about the migration window.</p>
    <time class="time" datetime="2026-09-25T09:56">4 minutes ago</time>
  </div>
  <button class="x" type="button" aria-label="Dismiss notification"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
</article>

<article class="notif ok">
  <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg></span>
  <div class="body">
    <h2><span class="sr-only">Success: </span><a href="#">Deployment finished</a></h2>
    <p>Build <strong>#1482</strong> is live on production. All 214 checks passed.</p>
    <time class="time" datetime="2026-09-25T09:42">18 minutes ago</time>
  </div>
  <button class="x" type="button" aria-label="Dismiss notification"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
</article>

<article class="notif warn">
  <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 4l9 16H3z"/><path d="M12 10v4M12 17h.01"/></svg></span>
  <div class="body">
    <h2><span class="sr-only">Warning: </span>Card expires this month</h2>
    <p>The card ending 4242 expires on 30 September. Update it to avoid a failed renewal.</p>
    <div class="act"><button class="pri" type="button">Update card</button><button type="button">Remind me later</button></div>
    <time class="time" datetime="2026-09-24">Yesterday</time>
  </div>
  <button class="x" type="button" aria-label="Dismiss notification"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
</article>
CSS
/* Notification cards. --tone colours the left edge, icon and primary button; --wash is the icon tile.
   A card that opens something puts a stretched link on its title (the link's ::after covers the card);
   the dismiss and action buttons sit above that layer so they stay clickable. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.notif{--tone:#3b82f6;--wash:#eff6ff;position:relative;width:390px;max-width:100%;display:flex;gap:13px;
  padding:15px 16px;background:#fff;border:1px solid #e9ecf1;border-left:4px solid var(--tone);
  border-radius:16px;transition:box-shadow .18s}
.notif:hover{box-shadow:0 10px 26px -18px rgba(16,24,40,.28)}
.notif.info{--tone:#3b82f6;--wash:#eff6ff}
.notif.ok{--tone:#16a34a;--wash:#effdf4}
.notif.warn{--tone:#b45309;--wash:#fffbeb}
.notif svg{display:block}
.notif .ic{width:34px;height:34px;border-radius:10px;background:var(--wash);color:var(--tone);
  display:grid;place-items:center;flex-shrink:0}
.notif .ic svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2.1}
.notif .body{flex:1;min-width:0}
.notif h2{font-size:.92rem;margin-bottom:3px;padding-right:22px}
.notif h2 a{color:inherit;text-decoration:none}
.notif h2 a::after{content:"";position:absolute;inset:0}
.notif h2 a:focus-visible{outline:2px solid transparent}
.notif:has(h2 a:focus-visible){outline:2px solid #4f46e5;outline-offset:2px}
@supports not selector(:has(*)){.notif h2 a:focus-visible{outline-color:#4f46e5;outline-offset:2px}}
.notif p{font-size:.85rem;color:#667085;line-height:1.55}
.notif .time{display:block;font-size:.75rem;color:#667085;margin-top:8px}
.notif .act{display:flex;flex-wrap:wrap;gap:8px;margin-top:11px}
.notif button{position:relative;z-index:1}
.notif button:focus-visible{outline:2px solid #4f46e5;outline-offset:2px}
.notif .act button{font:inherit;font-size:.79rem;font-weight:700;padding:6px 12px;border-radius:8px;cursor:pointer;
  border:1px solid #e4e7ec;background:#fff;color:#344054}
.notif .act button:hover{background:#f7f8fa}
.notif .act button.pri{background:var(--tone);border-color:var(--tone);color:#fff}
.notif .x{position:absolute;top:11px;right:11px;width:26px;height:26px;border:0;background:none;cursor:pointer;
  border-radius:7px;color:#667085;display:grid;place-items:center}
.notif .x:hover{background:#f2f4f7;color:#344054}
.notif .x svg{width:13px;height:13px;stroke:currentColor;fill:none;stroke-width:2.4}
@media (prefers-reduced-motion:reduce){.notif{transition:none}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<article class="card notif info">
  <div class="card-body d-flex">
    <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg></span>
    <div class="flex-grow-1 min-w-0">
      <h2 class="card-title"><span class="visually-hidden">Info: </span><a href="#" class="stretched-link">New comment on “Q3 rollout”</a></h2>
      <p class="card-text mb-0">Priya replied to your thread about the migration window.</p>
      <time class="time d-block" datetime="2026-09-25T09:56">4 minutes ago</time>
    </div>
    <button type="button" class="btn-close" aria-label="Dismiss notification"></button>
  </div>
</article>

<article class="card notif ok">
  <div class="card-body d-flex">
    <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg></span>
    <div class="flex-grow-1 min-w-0">
      <h2 class="card-title"><span class="visually-hidden">Success: </span><a href="#" class="stretched-link">Deployment finished</a></h2>
      <p class="card-text mb-0">Build <strong>#1482</strong> is live on production. All 214 checks passed.</p>
      <time class="time d-block" datetime="2026-09-25T09:42">18 minutes ago</time>
    </div>
    <button type="button" class="btn-close" aria-label="Dismiss notification"></button>
  </div>
</article>

<article class="card notif warn">
  <div class="card-body d-flex">
    <span class="ic" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 4l9 16H3z"/><path d="M12 10v4M12 17h.01"/></svg></span>
    <div class="flex-grow-1 min-w-0">
      <h2 class="card-title"><span class="visually-hidden">Warning: </span>Card expires this month</h2>
      <p class="card-text mb-0">The card ending 4242 expires on 30 September. Update it to avoid a failed renewal.</p>
      <div class="d-flex flex-wrap gap-2 mt-2 pt-1"><button type="button" class="btn btn-tone">Update card</button><button type="button" class="btn btn-quiet">Remind me later</button></div>
      <time class="time d-block" datetime="2026-09-24">Yesterday</time>
    </div>
    <button type="button" class="btn-close" aria-label="Dismiss notification"></button>
  </div>
</article>
CSS
/* Bootstrap .card + .stretched-link + .btn + .btn-close. --tone colours the left edge, icon and
   primary button; --wash is the icon tile. Buttons are lifted above the stretched link's layer. */
.notif{--tone:#3b82f6;--wash:#eff6ff;--bs-card-border-color:#e9ecf1;--bs-card-border-radius:16px;
  --bs-card-spacer-y:15px;--bs-card-spacer-x:16px;width:390px;max-width:100%;
  border-left:4px solid var(--tone);transition:box-shadow .18s}
.notif:hover{box-shadow:0 10px 26px -18px rgba(16,24,40,.28)}
.notif.info{--tone:#3b82f6;--wash:#eff6ff}
.notif.ok{--tone:#16a34a;--wash:#effdf4}
.notif.warn{--tone:#b45309;--wash:#fffbeb}
.notif .card-body{gap:13px}
.notif .min-w-0{min-width:0}
.notif .ic{display:grid;place-items:center;width:34px;height:34px;border-radius:10px;background:var(--wash);color:var(--tone);flex-shrink:0}
.notif .ic svg{width:18px;height:18px;stroke:currentColor;fill:none;stroke-width:2.1}
.notif .card-title{font-size:.92rem;font-weight:700;line-height:normal;margin-bottom:3px;padding-right:22px}
.notif .card-title a{color:inherit;text-decoration:none}
.notif .stretched-link:focus-visible{outline:2px solid transparent}
.notif:has(.stretched-link:focus-visible){outline:2px solid #4f46e5;outline-offset:2px}
@supports not selector(:has(*)){.notif .stretched-link:focus-visible{outline-color:#4f46e5;outline-offset:2px}}
.notif .card-text{font-size:.85rem;color:#667085;line-height:1.55}
.notif .time{font-size:.75rem;color:#667085;margin-top:8px}
.notif .btn,.notif .btn-close{position:relative;z-index:2}
.notif .btn{--bs-btn-font-size:.79rem;--bs-btn-font-weight:700;--bs-btn-padding-y:6px;--bs-btn-padding-x:12px;
  --bs-btn-border-radius:8px;--bs-btn-line-height:normal;--bs-btn-focus-box-shadow:0 0 0 2px #fff,0 0 0 4px #4f46e5}
.notif .btn-tone{--bs-btn-color:#fff;--bs-btn-bg:var(--tone);--bs-btn-border-color:var(--tone);
  --bs-btn-hover-color:#fff;--bs-btn-hover-bg:var(--tone);--bs-btn-hover-border-color:var(--tone);
  --bs-btn-active-color:#fff;--bs-btn-active-bg:var(--tone);--bs-btn-active-border-color:var(--tone)}
.notif .btn-quiet{--bs-btn-color:#344054;--bs-btn-bg:#fff;--bs-btn-border-color:#e4e7ec;
  --bs-btn-hover-color:#344054;--bs-btn-hover-bg:#f7f8fa;--bs-btn-hover-border-color:#e4e7ec;
  --bs-btn-active-bg:#f2f4f7;--bs-btn-active-border-color:#e4e7ec}
.notif .btn-close{--bs-btn-close-opacity:.62;--bs-btn-close-hover-opacity:.85;
  --bs-btn-close-focus-shadow:0 0 0 2px #4f46e5;position:absolute;top:11px;right:11px;
  width:10px;height:10px;padding:8px;background-size:9px;border-radius:7px}
.notif .btn-close:hover{background-color:#f2f4f7}
@media (prefers-reduced-motion:reduce){.notif,.notif .btn{transition:none}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<article class="relative flex w-[390px] max-w-full gap-[13px] rounded-2xl border border-l-4 border-[#e9ecf1] border-l-[#3b82f6] bg-white px-4 py-[15px] transition-shadow duration-[180ms] hover:shadow-[0_10px_26px_-18px_rgba(16,24,40,.28)] has-[a:focus-visible]:outline-2 has-[a:focus-visible]:outline-offset-2 has-[a:focus-visible]:outline-[#4f46e5] motion-reduce:transition-none">
  <span class="grid size-[34px] shrink-0 place-items-center rounded-[10px] bg-[#eff6ff] text-[#3b82f6]" aria-hidden="true"><svg class="block size-[18px] fill-none stroke-current stroke-[2.1]" viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"/><path d="M12 11v5M12 8h.01"/></svg></span>
  <div class="min-w-0 flex-1">
    <h2 class="mb-[3px] pr-[22px] text-[.92rem] font-bold"><span class="sr-only">Info: </span><a href="#" class="after:absolute after:inset-0 focus-visible:outline-2 focus-visible:outline-transparent">New comment on “Q3 rollout”</a></h2>
    <p class="text-[.85rem] leading-[1.55] text-[#667085]">Priya replied to your thread about the migration window.</p>
    <time class="mt-2 block text-xs text-[#667085]" datetime="2026-09-25T09:56">4 minutes ago</time>
  </div>
  <button class="absolute top-[11px] right-[11px] z-10 grid size-[26px] cursor-pointer place-items-center rounded-[7px] text-[#667085] hover:bg-[#f2f4f7] hover:text-[#344054] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#4f46e5]" type="button" aria-label="Dismiss notification"><svg class="block size-[13px] fill-none stroke-current stroke-[2.4]" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
</article>

<article class="relative flex w-[390px] max-w-full gap-[13px] rounded-2xl border border-l-4 border-[#e9ecf1] border-l-[#16a34a] bg-white px-4 py-[15px] transition-shadow duration-[180ms] hover:shadow-[0_10px_26px_-18px_rgba(16,24,40,.28)] has-[a:focus-visible]:outline-2 has-[a:focus-visible]:outline-offset-2 has-[a:focus-visible]:outline-[#4f46e5] motion-reduce:transition-none">
  <span class="grid size-[34px] shrink-0 place-items-center rounded-[10px] bg-[#effdf4] text-[#16a34a]" aria-hidden="true"><svg class="block size-[18px] fill-none stroke-current stroke-[2.1]" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg></span>
  <div class="min-w-0 flex-1">
    <h2 class="mb-[3px] pr-[22px] text-[.92rem] font-bold"><span class="sr-only">Success: </span><a href="#" class="after:absolute after:inset-0 focus-visible:outline-2 focus-visible:outline-transparent">Deployment finished</a></h2>
    <p class="text-[.85rem] leading-[1.55] text-[#667085]">Build <strong>#1482</strong> is live on production. All 214 checks passed.</p>
    <time class="mt-2 block text-xs text-[#667085]" datetime="2026-09-25T09:42">18 minutes ago</time>
  </div>
  <button class="absolute top-[11px] right-[11px] z-10 grid size-[26px] cursor-pointer place-items-center rounded-[7px] text-[#667085] hover:bg-[#f2f4f7] hover:text-[#344054] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#4f46e5]" type="button" aria-label="Dismiss notification"><svg class="block size-[13px] fill-none stroke-current stroke-[2.4]" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
</article>

<article class="relative flex w-[390px] max-w-full gap-[13px] rounded-2xl border border-l-4 border-[#e9ecf1] border-l-[#b45309] bg-white px-4 py-[15px] transition-shadow duration-[180ms] hover:shadow-[0_10px_26px_-18px_rgba(16,24,40,.28)] motion-reduce:transition-none">
  <span class="grid size-[34px] shrink-0 place-items-center rounded-[10px] bg-[#fffbeb] text-[#b45309]" aria-hidden="true"><svg class="block size-[18px] fill-none stroke-current stroke-[2.1]" viewBox="0 0 24 24"><path d="M12 4l9 16H3z"/><path d="M12 10v4M12 17h.01"/></svg></span>
  <div class="min-w-0 flex-1">
    <h2 class="mb-[3px] pr-[22px] text-[.92rem] font-bold"><span class="sr-only">Warning: </span>Card expires this month</h2>
    <p class="text-[.85rem] leading-[1.55] text-[#667085]">The card ending 4242 expires on 30 September. Update it to avoid a failed renewal.</p>
    <div class="mt-[11px] flex flex-wrap gap-2">
      <button class="cursor-pointer rounded-lg border border-[#b45309] bg-[#b45309] px-3 py-1.5 text-[.79rem] font-bold text-white focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#4f46e5]" type="button">Update card</button>
      <button class="cursor-pointer rounded-lg border border-[#e4e7ec] bg-white px-3 py-1.5 text-[.79rem] font-bold text-[#344054] hover:bg-[#f7f8fa] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#4f46e5]" type="button">Remind me later</button>
    </div>
    <time class="mt-2 block text-xs text-[#667085]" datetime="2026-09-24">Yesterday</time>
  </div>
  <button class="absolute top-[11px] right-[11px] z-10 grid size-[26px] cursor-pointer place-items-center rounded-[7px] text-[#667085] hover:bg-[#f2f4f7] hover:text-[#344054] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[#4f46e5]" type="button" aria-label="Dismiss notification"><svg class="block size-[13px] fill-none stroke-current stroke-[2.4]" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 6l12 12M18 6L6 18"/></svg></button>
</article>

About this set

Three notification cards in the info, success and warning severities, stacked the way they would sit in a notification panel. Each card has a coloured left edge, a matching icon tile, a bold title, a line of detail, a relative timestamp in a time element and a dismiss button in the top corner. The info card (a new comment) and the success card (a finished deployment) open something when clicked, so their titles are stretched links whose ::after layer covers the whole card; the warning card (a card about to expire) carries its own Update card and Remind me later buttons instead. The dismiss and action buttons sit above the link layer, so each stays a separate click target. Severity is not left to colour alone: a visually hidden Info, Success or Warning prefix is read before each title. One custom property, –tone, sets the edge, icon and primary button colour, and –wash sets the icon tile. The Bootstrap version uses .card, .stretched-link, .btn and the stock .btn-close; the Tailwind version draws the card focus ring with has-[a:focus-visible].

What’s included

  • Info, success and warning variants driven by one --tone variable
  • Stretched-link titles on the cards that open something
  • Dismiss and action buttons layered above the link
  • Hidden severity prefix so colour is not the only signal
  • Relative timestamps in time elements with a datetime value

Accessibility

Each card title is an h2 that starts with visually hidden severity text, and each linked card has a single link, so a screen reader hears one name per card. The icon-only dismiss buttons are labelled Dismiss notification and all icons are aria-hidden. Keyboard focus on a card link draws a 2px indigo ring around the whole card, buttons get their own ring, and the hover shadow transition is removed under prefers-reduced-motion.

Customise it

Set --tone and --wash on .info, .ok and .warn (plain CSS and Bootstrap) or swap the border-l-, bg- and text- colours on each card (Tailwind). Keep --tone dark enough for white button text; the warning amber is #b45309 for that reason.