Avatars & media
Represent users, accounts, and entities. Avatars surface identity at a glance — initials when no image is available, stacked when space is tight, paired with text in the media object pattern.
Sizes
Four sizes cover every density level — from inline mentions to full profile views. Always match avatar size to the surrounding text size and row height.
<span class="ws-avatar ws-avatar--xs">JD</span>
<span class="ws-avatar ws-avatar--sm">JD</span>
<span class="ws-avatar ws-avatar--md">JD</span>
<span class="ws-avatar ws-avatar--lg">JD</span>| Modifier | Size | Font | Typical use |
|---|---|---|---|
ws-avatar--xs | 24 × 24 px | 10 px | Inline mentions, compact tags, table badges |
ws-avatar--sm | 32 × 32 px | 12 px | Data table rows, activity feeds, nav items |
ws-avatar--md | 40 × 40 px | 14 px | Default — cards, comment threads, dropdowns |
ws-avatar--lg | 56 × 56 px | 18 px | Profile drawers, account headers, detail pages |
Initials & color variants
Render the first letter of given name + first letter of surname when no photo is available. Assign color deterministically from the user's ID — the same person always gets the same color, building recognition over time.
<span class="ws-avatar ws-avatar--md">AJ</span> <!-- navy (default) -->
<span class="ws-avatar ws-avatar--md ws-avatar--green">BK</span>
<span class="ws-avatar ws-avatar--md ws-avatar--amber">CL</span>
<span class="ws-avatar ws-avatar--md ws-avatar--teal">DM</span>
<span class="ws-avatar ws-avatar--md ws-avatar--coral">EN</span>
<span class="ws-avatar ws-avatar--md ws-avatar--violet">FP</span>Derive the color from a stable property of the user — their numeric ID modulo the number of variants works well: const idx = userId % COLOR_VARIANTS.length. Never randomize on each render — the same person must always appear in the same color for recognition to form.
| Modifier | Background | Foreground |
|---|---|---|
| default | --ws-green-01 (#319B42) | White |
ws-avatar--green | --green-600 | White |
ws-avatar--amber | --amber-600 | White |
ws-avatar--teal | #0d7f7f | White |
ws-avatar--coral | #c0473c | White |
ws-avatar--violet | #6d3db8 | White |
With photo
Drop an <img> inside .ws-avatar. The image fills and clips to a circle automatically. Always provide a meaningful alt attribute on the image.
<span class="ws-avatar ws-avatar--md">
<img src="/users/jane-doe.jpg" alt="Jane Doe" />
</span>If a profile photo fails to load, fall back to initials. Use an onerror handler that removes the <img> and sets the initials text on the parent span so the background color still shows.
Status indicator
Wrap the avatar in .ws-avatar-wrap and add a .ws-avatar-status sibling to overlay a presence dot. Use only on surfaces where real-time presence is genuinely meaningful — not decorative.
<div class="ws-avatar-wrap">
<span class="ws-avatar ws-avatar--md">JD</span>
<span class="ws-avatar-status ws-avatar-status--online" aria-label="Online"></span>
</div>| Modifier | Color | Meaning |
|---|---|---|
ws-avatar-status--online | Green | User is currently active and reachable |
ws-avatar-status--away | Amber | Idle or temporarily unavailable |
ws-avatar-status--busy | Red | In a meeting or Do Not Disturb |
ws-avatar-status--offline | Gray | Not logged in or status unknown |
Avatar groups
Stack multiple avatars with .ws-avatar-group. Beyond 3–4 avatars, collapse remaining members into a +N overflow counter to prevent visual noise.
3 assignees
7 assignees — overflow after 3
md size group
<div class="ws-avatar-group">
<span class="ws-avatar ws-avatar--sm">AJ</span>
<span class="ws-avatar ws-avatar--sm ws-avatar--green">BK</span>
<span class="ws-avatar ws-avatar--sm ws-avatar--amber">CL</span>
<!-- remaining 4 collapsed -->
<span class="ws-avatar ws-avatar--sm ws-avatar--overflow">+4</span>
</div>Wrap the overflow counter in a ws-tooltip-wrap to list all hidden member names on hover. Set aria-label="4 more: David M, Elena N, Frank P, Grace Q" on the overflow element so screen readers can announce them.
Media object
The media object is the most common avatar pattern — an avatar left-aligned with a name and secondary metadata beside it. Use in lists, feeds, comment threads, table rows, and notification panels.
<div class="ws-media">
<span class="ws-avatar ws-avatar--md">AJ</span>
<div class="ws-media__body">
<div class="ws-media__name">Alexandra Johnson</div>
<div class="ws-media__sub">Account Executive · San Francisco</div>
</div>
<!-- optional: badge, button, or time stamp -->
</div>Accessibility
Avatars represent a specific person — they are not decorative. Every avatar must either carry a text alternative or appear next to a visible name that acts as its label.
| Scenario | Required markup |
|---|---|
| Avatar with a visible name nearby (media object, table row) | Add aria-hidden="true" to the avatar element — the adjacent text already labels it. |
| Standalone avatar, no adjacent name | Add aria-label="Jane Doe" directly on .ws-avatar. |
| Avatar with a photo | Provide alt="Jane Doe" on the <img> — the circle container should be aria-hidden="true". |
| Status indicator dot | aria-label="Online" on .ws-avatar-status. Do not leave it unlabeled. |
| Overflow counter (+N) | aria-label="4 more assignees: David M, Elena N…" and a tooltip listing all names. |
The six color variants are a visual aid, not an identification mechanism. Don't rely on avatar color to convey meaning — always pair it with a name or label.