A .message lays out one message in a conversation. It
places an optional avatar, header and footer around a single
surface, usually a .message-bubble. Messages sit on the
start side. Add end for the sender's own messages.
Every child that is not the avatar, header or footer counts as the
surface, so a message has one surface. To keep a bubble and an
attachment together, wrap them in a <div>, or use
a group. Write the parts as
<div> elements. A <header> or
<footer> outside sectioning content becomes a page
landmark.
<div role="log" aria-label="Conversation with Oliver">
<div class="message end">
<p class="message-bubble">Deploying to prod real quick.</p>
</div>
<div class="message">
<p class="message-bubble">It's 4:55 PM. On a Friday.</p>
</div>
</div>
Put role="log" on the conversation so screen readers
announce messages appended to it. Leave it off a transcript that
does not change.
Avatar
Put a .message-avatar first in the message. It anchors
to the bottom of the surface and stays clear of the footer. On an
end message it moves to the end. The avatar is an
<img>, or a <span> holding
initials or an icon. Give the image an empty alt when a
header already names the sender.
<div class="message end">
<img class="message-avatar" src="me.jpg" alt="You">
<p class="message-bubble">It's a one-line change.</p>
</div>
<div class="message">
<span class="message-avatar" role="img" aria-label="Oliver">OL</span>
<p class="message-bubble">Alright, let me take a look.</p>
</div>
Group
A .message-group stacks consecutive messages from one
sender and joins their bubbles on the sender's side. Give the earlier
messages an empty .message-avatar so they line up with
the avatar on the last one.
<div class="message-group">
<div class="message">
<span class="message-avatar"></span>
<p class="message-bubble">I checked the registry addresses.</p>
</div>
<div class="message">
<span class="message-avatar" role="img" aria-label="Oliver">OL</span>
<p class="message-bubble">The component and example JSON now live under the UI registry.</p>
</div>
</div>
Actions
Message actions such as copy, feedback or retry go in the footer as
icon buttons. Each needs an
aria-label. On an end message the actions
stay on the end side.
<div class="message">
<p class="message-bubble">The install failure is coming from the workspace package.</p>
<div class="message-footer">
<button class="icon-button xsmall" aria-label="Copy">
<span class="material-symbols" aria-hidden="true">content_copy</span>
</button>
<button class="icon-button xsmall" aria-label="Good response">
<span class="material-symbols" aria-hidden="true">thumb_up</span>
</button>
</div>
</div>
<div class="message end">
<p class="message-bubble">Okay drop me a link. Taking a look…</p>
<div class="message-footer">
<span class="error-text">Failed to send</span>
<button class="icon-button xsmall" aria-label="Retry">
<span class="material-symbols" aria-hidden="true">refresh</span>
</button>
</div>
</div>
Attachments
Use an outlined bubble, which has no fill, for attachments and
other rich content. A bubble whose only child is an image or video
frames it with a thin inset. Send several items as a group.
<div class="message end">
<div class="message-bubble outlined">
<img src="office.jpg" alt="Office corridor with glass walls" width="80" height="80">
</div>
</div>
<div class="message">
<div class="message-bubble outlined flex align-center gap-3">
<span class="material-symbols" aria-hidden="true">description</span>
<div class="min-w-0">
<div class="title-small truncate">sales-dashboard.pdf</div>
<div class="body-small">PDF · 2.4 MB</div>
</div>
<a class="icon-button" href="sales-dashboard.pdf" download aria-label="Download sales-dashboard.pdf">
<span class="material-symbols" aria-hidden="true">download</span>
</a>
</div>
</div>
Tokens
Override these on the .message, or on
.message-group for the group gap.
| Token | Default |
|---|---|
--md-comp-message-avatar-size |
32px |
--md-comp-message-gap |
8px |
--md-comp-message-surface-max-width |
80% |
--md-comp-message-bubble-shape |
20px |
--md-comp-message-bubble-grouped-shape |
4px |
--md-comp-message-bubble-container-color |
--md-sys-color-surface-container-high; end: --md-sys-color-primary-container |
--md-comp-message-bubble-color |
--md-sys-color-on-surface; end: --md-sys-color-on-primary-container |
--md-comp-message-group-gap |
2px |