Open demo

CSS code

HTML
<div><span class="lbl">Grouped corners, curved tail on the last bubble</span>
<section class="cs cs-curved" aria-label="Conversation with Ines Duarte">
  <p class="cs-day"><time datetime="2026-10-13T16:02">Tuesday 16:02</time></p>
  <div class="cs-group in">
    <p class="cs-msg"><span class="sr-only">Ines: </span>Did the bike shop call you back?</p>
    <p class="cs-msg">Mine's been there since Monday.</p>
  </div>
  <div class="cs-group out">
    <p class="cs-msg"><span class="sr-only">You: </span>Yes, mine's ready.</p>
    <p class="cs-msg">They replaced the chain and both brake pads.</p>
    <p class="cs-msg">€64 in total, which felt fair.</p>
  </div>
  <div class="cs-group in">
    <p class="cs-msg"><span class="sr-only">Ines: </span>Nice. I'll ask them to look at my gears too.</p>
  </div>
  <div class="cs-group out">
    <p class="cs-msg"><span class="sr-only">You: </span>Pick them up together on Thursday after work?</p>
  </div>
  <div class="cs-group in">
    <p class="cs-msg"><span class="sr-only">Ines: </span>Deal. 17:45 outside the shop.</p>
  </div>
  <p class="cs-meta">Delivered</p>
</section></div>

<div><span class="lbl">Notched tail on the first bubble, time inside</span>
<section class="cs cs-notch" aria-label="Conversation with Ines Duarte, notched style">
  <p class="cs-day"><time datetime="2026-10-13">Tuesday</time></p>
  <div class="cs-group in">
    <p class="cs-msg"><span><span class="sr-only">Ines: </span>Did the bike shop call you back?</span> <time datetime="2026-10-13T16:02">16:02</time></p>
    <p class="cs-msg"><span>Mine's been there since Monday.</span> <time datetime="2026-10-13T16:02">16:02</time></p>
  </div>
  <div class="cs-group out">
    <p class="cs-msg"><span><span class="sr-only">You: </span>Yes, mine's ready.</span> <time datetime="2026-10-13T16:05">16:05</time></p>
    <p class="cs-msg"><span>They replaced the chain and both brake pads.</span> <time datetime="2026-10-13T16:05">16:05</time></p>
    <p class="cs-msg"><span>€64 in total, which felt fair.</span> <time datetime="2026-10-13T16:06">16:06</time></p>
  </div>
  <div class="cs-group in">
    <p class="cs-msg"><span><span class="sr-only">Ines: </span>Nice. I'll ask them to look at my gears too.</span> <time datetime="2026-10-13T16:09">16:09</time></p>
  </div>
  <div class="cs-group out">
    <p class="cs-msg"><span><span class="sr-only">You: </span>Pick them up together on Thursday after work?</span> <time datetime="2026-10-13T16:10">16:10</time></p>
  </div>
  <div class="cs-group in">
    <p class="cs-msg"><span><span class="sr-only">Ines: </span>Deal. 17:45 outside the shop.</span> <time datetime="2026-10-13T16:12">16:12</time></p>
  </div>
</section></div>
CSS
/* Chat bubbles with tails. Consecutive messages from one sender sit in a .cs-group; the corners facing the
   sender stay tight between bubbles, and only one bubble per group carries the tail. */
.cs{--cs-in:#e9e9f0;--cs-in-ink:#1c1d24;--cs-out:#0862cf;--cs-out-ink:#fff;--cs-muted:#5d606c;--cs-bg:#fff;--cs-r:20px;--cs-t:5px;
  display:flex;flex-direction:column;gap:12px;padding:22px 22px 18px;border-radius:24px;background:var(--cs-bg);
  box-shadow:0 1px 2px rgba(28,29,36,.06),0 18px 40px -22px rgba(28,29,36,.35);font-size:.95rem;line-height:1.4}
.cs .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}
.cs-day{margin:0 0 4px;text-align:center;font-size:.75rem;font-weight:600;color:var(--cs-muted)}
.cs-group{display:flex;flex-direction:column;align-items:flex-start;gap:3px}
.cs-group.out{align-items:flex-end}
.cs-msg{position:relative;width:fit-content;max-width:78%;margin:0;padding:8px 14px;background:var(--cs-in);color:var(--cs-in-ink);overflow-wrap:anywhere}
.out .cs-msg{background:var(--cs-out);color:var(--cs-out-ink)}
.cs-meta{align-self:flex-end;margin:2px 4px 0;font-size:.72rem;color:var(--cs-muted)}

/* Style 1: grouped corners, curved tail on the last bubble. The tail is a radial-gradient cut-out,
   so it needs no knowledge of the background behind the chat. */
.cs-curved .in .cs-msg{border-radius:var(--cs-t) var(--cs-r) var(--cs-r) var(--cs-t)}
.cs-curved .out .cs-msg{border-radius:var(--cs-r) var(--cs-t) var(--cs-t) var(--cs-r)}
.cs-curved .in .cs-msg:first-child{border-top-left-radius:var(--cs-r)}
.cs-curved .out .cs-msg:first-child{border-top-right-radius:var(--cs-r)}
.cs-curved .cs-msg:last-child::after{content:"";position:absolute;bottom:0;width:15px;height:18px}
.cs-curved .in .cs-msg:last-child::after{left:-7px;background:radial-gradient(7px 18px at 0 0,transparent 96%,var(--cs-in) 100%)}
.cs-curved .out .cs-msg:last-child::after{right:-7px;background:radial-gradient(7px 18px at 100% 0,transparent 96%,var(--cs-out) 100%)}

/* Style 2: notched tail on the first bubble of each group, time inside the bubble */
.cs-notch{--cs-bg:#efe6da;--cs-in:#fff;--cs-out:#d3f4c4;--cs-out-ink:#10251a;--cs-muted:#5a5248;--cs-r:10px}
.cs-notch .cs-msg{display:flex;flex-wrap:wrap;align-items:flex-end;column-gap:10px;border-radius:var(--cs-r);box-shadow:0 1px 1px rgba(60,45,30,.14)}
.cs-notch .cs-msg time{margin-left:auto;font-size:.7rem;color:var(--cs-muted);white-space:nowrap}
.cs-notch .cs-group{gap:4px}
.cs-notch .in .cs-msg:first-child{border-top-left-radius:0}
.cs-notch .out .cs-msg:first-child{border-top-right-radius:0}
.cs-notch .cs-msg:first-child::before{content:"";position:absolute;top:0;width:9px;height:13px}
.cs-notch .in .cs-msg:first-child::before{right:100%;background:var(--cs-in);clip-path:polygon(0 0,100% 0,100% 100%)}
.cs-notch .out .cs-msg:first-child::before{left:100%;background:var(--cs-out);clip-path:polygon(0 0,100% 0,0 100%)}
.cs-notch .cs-day{align-self:center;padding:3px 12px;border-radius:8px;background:#fbf7f1;color:var(--cs-muted)}
@media (max-width:420px){.cs{padding:18px 16px 14px}.cs-msg{max-width:86%}}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl">Grouped corners, curved tail on the last bubble</span>
<section class="card border-0 cs cs-curved" aria-label="Conversation with Ines Duarte">
  <p class="cs-day small fw-semibold text-center"><time datetime="2026-10-13T16:02">Tuesday 16:02</time></p>
  <div class="cs-group in d-flex flex-column align-items-start">
    <p class="cs-msg mb-0"><span class="visually-hidden">Ines: </span>Did the bike shop call you back?</p>
    <p class="cs-msg mb-0">Mine's been there since Monday.</p>
  </div>
  <div class="cs-group out d-flex flex-column align-items-end">
    <p class="cs-msg mb-0"><span class="visually-hidden">You: </span>Yes, mine's ready.</p>
    <p class="cs-msg mb-0">They replaced the chain and both brake pads.</p>
    <p class="cs-msg mb-0">€64 in total, which felt fair.</p>
  </div>
  <div class="cs-group in d-flex flex-column align-items-start">
    <p class="cs-msg mb-0"><span class="visually-hidden">Ines: </span>Nice. I'll ask them to look at my gears too.</p>
  </div>
  <div class="cs-group out d-flex flex-column align-items-end">
    <p class="cs-msg mb-0"><span class="visually-hidden">You: </span>Pick them up together on Thursday after work?</p>
  </div>
  <div class="cs-group in d-flex flex-column align-items-start">
    <p class="cs-msg mb-0"><span class="visually-hidden">Ines: </span>Deal. 17:45 outside the shop.</p>
  </div>
  <p class="cs-meta small">Delivered</p>
</section></div>

<div><span class="lbl">Notched tail on the first bubble, time inside</span>
<section class="card border-0 cs cs-notch" aria-label="Conversation with Ines Duarte, notched style">
  <p class="cs-day small fw-semibold text-center"><time datetime="2026-10-13">Tuesday</time></p>
  <div class="cs-group in d-flex flex-column align-items-start">
    <p class="cs-msg mb-0"><span><span class="visually-hidden">Ines: </span>Did the bike shop call you back?</span> <time datetime="2026-10-13T16:02">16:02</time></p>
    <p class="cs-msg mb-0"><span>Mine's been there since Monday.</span> <time datetime="2026-10-13T16:02">16:02</time></p>
  </div>
  <div class="cs-group out d-flex flex-column align-items-end">
    <p class="cs-msg mb-0"><span><span class="visually-hidden">You: </span>Yes, mine's ready.</span> <time datetime="2026-10-13T16:05">16:05</time></p>
    <p class="cs-msg mb-0"><span>They replaced the chain and both brake pads.</span> <time datetime="2026-10-13T16:05">16:05</time></p>
    <p class="cs-msg mb-0"><span>€64 in total, which felt fair.</span> <time datetime="2026-10-13T16:06">16:06</time></p>
  </div>
  <div class="cs-group in d-flex flex-column align-items-start">
    <p class="cs-msg mb-0"><span><span class="visually-hidden">Ines: </span>Nice. I'll ask them to look at my gears too.</span> <time datetime="2026-10-13T16:09">16:09</time></p>
  </div>
  <div class="cs-group out d-flex flex-column align-items-end">
    <p class="cs-msg mb-0"><span><span class="visually-hidden">You: </span>Pick them up together on Thursday after work?</span> <time datetime="2026-10-13T16:10">16:10</time></p>
  </div>
  <div class="cs-group in d-flex flex-column align-items-start">
    <p class="cs-msg mb-0"><span><span class="visually-hidden">Ines: </span>Deal. 17:45 outside the shop.</span> <time datetime="2026-10-13T16:12">16:12</time></p>
  </div>
</section></div>
CSS
/* Chat bubbles with tails on a Bootstrap .card (flex utilities lay out the groups, .visually-hidden names the sender). Consecutive messages from one sender sit in a .cs-group; the corners facing the
   sender stay tight between bubbles, and only one bubble per group carries the tail. */
.cs{--cs-in:#e9e9f0;--cs-in-ink:#1c1d24;--cs-out:#0862cf;--cs-out-ink:#fff;--cs-muted:#5d606c;--cs-bg:#fff;--cs-r:20px;--cs-t:5px;
  display:flex;flex-direction:column;gap:12px;padding:22px 22px 18px;border-radius:24px;background:var(--cs-bg);
  box-shadow:0 1px 2px rgba(28,29,36,.06),0 18px 40px -22px rgba(28,29,36,.35);font-size:.95rem;line-height:1.4}
.cs-day{margin:0 0 4px;text-align:center;font-size:.75rem;font-weight:600;color:var(--cs-muted)}
.cs-group{display:flex;flex-direction:column;align-items:flex-start;gap:3px}
.cs-group.out{align-items:flex-end}
.cs-msg{position:relative;width:fit-content;max-width:78%;margin:0;padding:8px 14px;background:var(--cs-in);color:var(--cs-in-ink);overflow-wrap:anywhere}
.out .cs-msg{background:var(--cs-out);color:var(--cs-out-ink)}
.cs-meta{align-self:flex-end;margin:2px 4px 0;font-size:.72rem;color:var(--cs-muted)}

/* Style 1: grouped corners, curved tail on the last bubble. The tail is a radial-gradient cut-out,
   so it needs no knowledge of the background behind the chat. */
.cs-curved .in .cs-msg{border-radius:var(--cs-t) var(--cs-r) var(--cs-r) var(--cs-t)}
.cs-curved .out .cs-msg{border-radius:var(--cs-r) var(--cs-t) var(--cs-t) var(--cs-r)}
.cs-curved .in .cs-msg:first-child{border-top-left-radius:var(--cs-r)}
.cs-curved .out .cs-msg:first-child{border-top-right-radius:var(--cs-r)}
.cs-curved .cs-msg:last-child::after{content:"";position:absolute;bottom:0;width:15px;height:18px}
.cs-curved .in .cs-msg:last-child::after{left:-7px;background:radial-gradient(7px 18px at 0 0,transparent 96%,var(--cs-in) 100%)}
.cs-curved .out .cs-msg:last-child::after{right:-7px;background:radial-gradient(7px 18px at 100% 0,transparent 96%,var(--cs-out) 100%)}

/* Style 2: notched tail on the first bubble of each group, time inside the bubble */
.cs-notch{--cs-bg:#efe6da;--cs-in:#fff;--cs-out:#d3f4c4;--cs-out-ink:#10251a;--cs-muted:#5a5248;--cs-r:10px}
.cs-notch .cs-msg{display:flex;flex-wrap:wrap;align-items:flex-end;column-gap:10px;border-radius:var(--cs-r);box-shadow:0 1px 1px rgba(60,45,30,.14)}
.cs-notch .cs-msg time{margin-left:auto;font-size:.7rem;color:var(--cs-muted);white-space:nowrap}
.cs-notch .cs-group{gap:4px}
.cs-notch .in .cs-msg:first-child{border-top-left-radius:0}
.cs-notch .out .cs-msg:first-child{border-top-right-radius:0}
.cs-notch .cs-msg:first-child::before{content:"";position:absolute;top:0;width:9px;height:13px}
.cs-notch .in .cs-msg:first-child::before{right:100%;background:var(--cs-in);clip-path:polygon(0 0,100% 0,100% 100%)}
.cs-notch .out .cs-msg:first-child::before{left:100%;background:var(--cs-out);clip-path:polygon(0 0,100% 0,0 100%)}
.cs-notch .cs-day{align-self:center;padding:3px 12px;border-radius:8px;background:#fbf7f1;color:var(--cs-muted)}
@media (max-width:420px){.cs{padding:18px 16px 14px}.cs-msg{max-width:86%}}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#575b68] uppercase">Grouped corners, curved tail on the last bubble</span>
<section class="flex flex-col gap-3 rounded-3xl px-[22px] pt-[22px] pb-[18px] text-[.95rem] leading-[1.4] shadow-[0_1px_2px_rgba(28,29,36,.06),0_18px_40px_-22px_rgba(28,29,36,.35)] max-[420px]:px-4 max-[420px]:pt-[18px] max-[420px]:pb-3.5 bg-white" aria-label="Conversation with Ines Duarte">
  <p class="mb-1 text-center text-xs font-semibold text-cs-muted"><time datetime="2026-10-13T16:02">Tuesday 16:02</time></p>
  <div class="flex flex-col gap-[3px] items-start">
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[20px_20px_20px_5px] bg-cs-in text-cs-ink"><span class="sr-only">Ines: </span>Did the bike shop call you back?</p>
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[5px_20px_20px_4px] bg-cs-in text-cs-ink cs-tail-in">Mine's been there since Monday.</p>
  </div>
  <div class="flex flex-col gap-[3px] items-end">
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[20px_20px_5px_20px] bg-cs-out text-white"><span class="sr-only">You: </span>Yes, mine's ready.</p>
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[20px_5px_5px_20px] bg-cs-out text-white">They replaced the chain and both brake pads.</p>
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[20px_5px_4px_20px] bg-cs-out text-white cs-tail-out">€64 in total, which felt fair.</p>
  </div>
  <div class="flex flex-col gap-[3px] items-start">
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[20px_20px_20px_4px] bg-cs-in text-cs-ink cs-tail-in"><span class="sr-only">Ines: </span>Nice. I'll ask them to look at my gears too.</p>
  </div>
  <div class="flex flex-col gap-[3px] items-end">
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[20px_20px_4px_20px] bg-cs-out text-white cs-tail-out"><span class="sr-only">You: </span>Pick them up together on Thursday after work?</p>
  </div>
  <div class="flex flex-col gap-[3px] items-start">
    <p class="relative w-fit max-w-[78%] px-3.5 py-2 [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[20px_20px_20px_4px] bg-cs-in text-cs-ink cs-tail-in"><span class="sr-only">Ines: </span>Deal. 17:45 outside the shop.</p>
  </div>
  <p class="mx-1 mt-0.5 self-end text-[.72rem] text-cs-muted">Delivered</p>
</section></div>

<div><span class="mb-4 block text-[.72rem] tracking-[.12em] text-[#575b68] uppercase">Notched tail on the first bubble, time inside</span>
<section class="flex flex-col gap-3 rounded-3xl px-[22px] pt-[22px] pb-[18px] text-[.95rem] leading-[1.4] shadow-[0_1px_2px_rgba(28,29,36,.06),0_18px_40px_-22px_rgba(28,29,36,.35)] max-[420px]:px-4 max-[420px]:pt-[18px] max-[420px]:pb-3.5 bg-[#efe6da]" aria-label="Conversation with Ines Duarte, notched style">
  <p class="mb-1 self-center rounded-lg bg-[#fbf7f1] px-3 py-[3px] text-xs font-semibold text-[#5a5248]"><time datetime="2026-10-13">Tuesday</time></p>
  <div class="flex flex-col gap-1 items-start">
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[0_10px_10px_10px] bg-white text-cs-ink cs-notch-in"><span><span class="sr-only">Ines: </span>Did the bike shop call you back?</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:02">16:02</time></p>
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[10px] bg-white text-cs-ink"><span>Mine's been there since Monday.</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:02">16:02</time></p>
  </div>
  <div class="flex flex-col gap-1 items-end">
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[10px_0_10px_10px] bg-[#d3f4c4] text-[#10251a] cs-notch-out"><span><span class="sr-only">You: </span>Yes, mine's ready.</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:05">16:05</time></p>
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[10px] bg-[#d3f4c4] text-[#10251a]"><span>They replaced the chain and both brake pads.</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:05">16:05</time></p>
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[10px] bg-[#d3f4c4] text-[#10251a]"><span>€64 in total, which felt fair.</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:06">16:06</time></p>
  </div>
  <div class="flex flex-col gap-1 items-start">
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[0_10px_10px_10px] bg-white text-cs-ink cs-notch-in"><span><span class="sr-only">Ines: </span>Nice. I'll ask them to look at my gears too.</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:09">16:09</time></p>
  </div>
  <div class="flex flex-col gap-1 items-end">
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[10px_0_10px_10px] bg-[#d3f4c4] text-[#10251a] cs-notch-out"><span><span class="sr-only">You: </span>Pick them up together on Thursday after work?</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:10">16:10</time></p>
  </div>
  <div class="flex flex-col gap-1 items-start">
    <p class="relative flex w-fit max-w-[78%] flex-wrap items-end gap-x-2.5 px-3.5 py-2 shadow-[0_1px_1px_rgba(60,45,30,.14)] [overflow-wrap:anywhere] max-[420px]:max-w-[86%] rounded-[0_10px_10px_10px] bg-white text-cs-ink cs-notch-in"><span><span class="sr-only">Ines: </span>Deal. 17:45 outside the shop.</span> <time class="ml-auto text-[.7rem] whitespace-nowrap text-[#5a5248]" datetime="2026-10-13T16:12">16:12</time></p>
  </div>
</section></div>
CSS
@theme {
  --color-cs-in:#e9e9f0; --color-cs-out:#0862cf; --color-cs-ink:#1c1d24; --color-cs-muted:#5d606c;
}
/* Utilities draw each bubble and its grouped corners; the tails are repeated pseudo-elements, so they live here.
   Curved tail: a radial-gradient cut-out that needs no knowledge of the background behind the chat. */
.cs-tail-in::after,.cs-tail-out::after{content:"";position:absolute;bottom:0;width:15px;height:18px}
.cs-tail-in::after{left:-7px;background:radial-gradient(7px 18px at 0 0,transparent 96%,var(--color-cs-in) 100%)}
.cs-tail-out::after{right:-7px;background:radial-gradient(7px 18px at 100% 0,transparent 96%,var(--color-cs-out) 100%)}
/* Notched tail: a clipped triangle in the bubble's own colour */
.cs-notch-in::before,.cs-notch-out::before{content:"";position:absolute;top:0;width:9px;height:13px}
.cs-notch-in::before{right:100%;background:#fff;clip-path:polygon(0 0,100% 0,100% 100%)}
.cs-notch-out::before{left:100%;background:#d3f4c4;clip-path:polygon(0 0,100% 0,0 100%)}

About this set

One short conversation about picking up two bikes from a repair shop, styled two ways so you can compare the two tail styles messaging apps use. Grouped corners, curved tail on the last bubble keeps consecutive messages from one sender together: the corners facing the sender stay tight between bubbles, the first bubble keeps its round top corner and only the last bubble of each group gets the curved tail. That tail is a radial-gradient cut-out on a pseudo-element, so it needs no knowledge of the background behind the chat and works on any colour or image. Notched tail on the first bubble, time inside puts a small clipped triangle on the first bubble of each group, squares off that corner and sets the time inside every bubble as a time element. Sent and received bubbles differ in colour and side, and each sender group starts with a visually hidden name such as Ines: or You:, so the conversation still reads correctly to people who cannot see which side a bubble is on. This set is about the bubbles themselves; for whole messenger layouts see the chat UI pack.

What’s included

  • Grouped corners that stay tight on the sender's side
  • Curved tail drawn with a radial-gradient, independent of the background
  • Notched first-bubble tail with the time inside the bubble
  • Visually hidden sender names at the start of each group
  • No JavaScript

Accessibility

Each conversation is a section with an aria-label such as Conversation with Ines Duarte. Every sender group starts with a visually hidden name, times are time elements with a datetime attribute, and the delivered receipt is written as text. Text in both sent and received bubbles reaches at least 4.5:1, and the tails are empty pseudo-elements that are not announced.

Customise it

Set --cs-in, --cs-out, --cs-out-ink and --cs-r on .cs, and the .cs-notch block for the second style. In Tailwind edit the --color-cs-* theme colours and the rounded-[…] utilities on each bubble; Bootstrap uses the same --cs-* variables on a .card.