UI Components Easy
Chat Bubble
Chat message bubbles with sender/receiver variants, avatar, timestamp, status indicators (sent/delivered/read), and grouping.
Open in Lab
MCP
css
Targets: HTML
Code
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: Inter, system-ui, sans-serif;
background: #050910;
color: #f2f6ff;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
}
.demo {
width: 100%;
max-width: 480px;
}
.demo-title {
font-size: 1.5rem;
font-weight: 800;
margin-bottom: 0.375rem;
}
.demo-sub {
color: #475569;
font-size: 0.875rem;
margin-bottom: 1.5rem;
}
/* โโ Chat window โโ */
.chat-window {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 1.25rem;
padding: 1.25rem;
display: flex;
flex-direction: column;
gap: 0.75rem;
}
/* โโ Date separator โโ */
.chat-separator {
display: flex;
align-items: center;
gap: 0.75rem;
margin: 0.25rem 0;
}
.chat-separator::before,
.chat-separator::after {
content: "";
flex: 1;
height: 1px;
background: rgba(255, 255, 255, 0.07);
}
.chat-separator span {
font-size: 0.7rem;
font-weight: 600;
letter-spacing: 0.06em;
text-transform: uppercase;
color: #475569;
white-space: nowrap;
}
/* โโ Message row โโ */
.chat-row {
display: flex;
gap: 0.625rem;
align-items: flex-end;
}
.chat-row--sent {
flex-direction: row-reverse;
}
.chat-row--grouped {
margin-top: -0.375rem;
}
/* โโ Avatar โโ */
.chat-avatar {
width: 2rem;
height: 2rem;
border-radius: 50%;
background: rgba(56, 189, 248, 0.15);
border: 1px solid rgba(56, 189, 248, 0.25);
color: #38bdf8;
font-size: 0.75rem;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
text-transform: uppercase;
}
.chat-avatar-spacer {
width: 2rem;
flex-shrink: 0;
}
/* โโ Message group โโ */
.chat-group {
display: flex;
flex-direction: column;
gap: 0.25rem;
max-width: 75%;
}
.chat-row--sent .chat-group {
align-items: flex-end;
}
.chat-sender-name {
font-size: 0.7rem;
font-weight: 600;
color: #475569;
padding-left: 0.75rem;
}
/* โโ Bubble โโ */
.chat-bubble {
padding: 0.625rem 0.875rem;
border-radius: 1.125rem;
font-size: 0.875rem;
line-height: 1.55;
word-break: break-word;
}
.chat-bubble--received {
background: rgba(255, 255, 255, 0.06);
border: 1px solid rgba(255, 255, 255, 0.08);
color: #cbd5e1;
border-bottom-left-radius: 0.375rem;
}
.chat-bubble--sent {
background: rgba(56, 189, 248, 0.15);
border: 1px solid rgba(56, 189, 248, 0.25);
color: #e0f2fe;
border-bottom-right-radius: 0.375rem;
}
/* โโ Timestamp & status โโ */
.chat-time {
font-size: 0.68rem;
color: #334155;
padding: 0 0.25rem;
}
.chat-meta {
display: flex;
align-items: center;
gap: 0.25rem;
justify-content: flex-end;
}
.chat-status {
display: flex;
align-items: center;
color: #334155;
}
.chat-status--delivered {
color: #475569;
}
.chat-status--read {
color: #38bdf8;
}<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Chat Bubble</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="demo">
<h1 class="demo-title">Chat Bubble</h1>
<p class="demo-sub">Sender/receiver variants with status indicators and grouping.</p>
<div class="chat-window">
<!-- Date separator -->
<div class="chat-separator" role="separator" aria-label="Today">
<span>Today</span>
</div>
<!-- Received message -->
<div class="chat-row chat-row--received" aria-label="Message from Alex">
<div class="chat-avatar" aria-hidden="true">A</div>
<div class="chat-group">
<span class="chat-sender-name">Alex</span>
<div class="chat-bubble chat-bubble--received">
Hey! Did you get a chance to review the design mockups I sent over?
</div>
<span class="chat-time">10:42 AM</span>
</div>
</div>
<!-- Received grouped (no avatar repeat) -->
<div class="chat-row chat-row--received chat-row--grouped" aria-label="Message from Alex">
<div class="chat-avatar-spacer" aria-hidden="true"></div>
<div class="chat-group">
<div class="chat-bubble chat-bubble--received">
I also added some notes in the Figma file for context.
</div>
<span class="chat-time">10:43 AM</span>
</div>
</div>
<!-- Sent message -->
<div class="chat-row chat-row--sent" aria-label="Sent message">
<div class="chat-group">
<div class="chat-bubble chat-bubble--sent">
Yes! Just finished going through them. The color palette is perfect.
</div>
<div class="chat-meta">
<span class="chat-time">10:47 AM</span>
<span class="chat-status chat-status--delivered" aria-label="Delivered">
<!-- Double check icon -->
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M2 12l5 5L17 7"/>
<path d="M8 12l5 5 7-10" opacity="0.6"/>
</svg>
</span>
</div>
</div>
</div>
<!-- Sent grouped -->
<div class="chat-row chat-row--sent chat-row--grouped" aria-label="Sent message">
<div class="chat-group">
<div class="chat-bubble chat-bubble--sent">
One thing โ can we revisit the spacing on the card component?
</div>
<div class="chat-meta">
<span class="chat-time">10:48 AM</span>
<span class="chat-status chat-status--sent" aria-label="Sent">
<!-- Single check icon -->
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M5 12l5 5L19 7"/>
</svg>
</span>
</div>
</div>
</div>
<!-- Received -->
<div class="chat-row chat-row--received" aria-label="Message from Alex">
<div class="chat-avatar" aria-hidden="true">A</div>
<div class="chat-group">
<div class="chat-bubble chat-bubble--received">
Totally agree. I'll bump the padding from 16px to 24px. Let me push an update now.
</div>
<span class="chat-time">10:51 AM</span>
</div>
</div>
<!-- Sent โ read status -->
<div class="chat-row chat-row--sent" aria-label="Sent message">
<div class="chat-group">
<div class="chat-bubble chat-bubble--sent">
๐ Perfect, thanks!
</div>
<div class="chat-meta">
<span class="chat-time">10:52 AM</span>
<span class="chat-status chat-status--read" aria-label="Read">
<!-- Blue double check -->
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M2 12l5 5L17 7"/>
<path d="M8 12l5 5 7-10"/>
</svg>
</span>
</div>
</div>
</div>
</div>
</div>
</body>
</html>Chat Bubble
Message bubble components for chat interfaces, supporting both sent (outgoing) and received (incoming) variants with full status indicators.
Variants
- Sent โ right-aligned bubble with accent background (your messages)
- Received โ left-aligned bubble with subtle background (othersโ messages)
- Grouped โ consecutive messages from the same sender collapse avatar and reduce spacing
Status indicators
sent ยท delivered ยท read
Each status is represented by a small icon below the sent message (single check โ double check โ blue double check).
Features
- Pure CSS with no JavaScript
- Avatar with fallback initials
- Timestamps on each message
- Grouping reduces visual clutter for rapid-fire messages
- Accessible with
role="log"andaria-labelon the chat container