ComponentsAvatar
Avatar
atomA user image or initials, with sizes and a status dot.
Avatar
Sizes, status dot and an overlapping group.
JMACMKLNEF
JMACMKRP+3
photo · photo · broken→initialsRecipe CSS
This is the exact CSS your kit ships for Avatar — token-driven, so it re-themes with every knob. Get it (and the rest) from the configurator's Use kit panel.
/* === Avatar — sizes, group stack, status dot === */
.avatar {
width: var(--k-avatar);
height: var(--k-avatar);
border-radius: 50%;
background: var(--k-primary-soft);
color: var(--k-primary-soft-fg);
display: inline-grid;
place-items: center;
font-size: var(--k-type-eyebrow);
font-weight: var(--k-weight-semibold);
position: relative;
flex: none;
}
.avatar--sm { width: calc(var(--k-avatar) - 0.375rem); height: calc(var(--k-avatar) - 0.375rem); font-size: var(--k-type-caption); }
.avatar--lg { width: calc(var(--k-avatar) + 0.5rem); height: calc(var(--k-avatar) + 0.5rem); font-size: var(--k-type-small); }
/* Photo avatar — the <img> covers the initials once it loads; on a broken/slow
src the consumer removes it (onError) and the initials underneath show through.
No layout shift either way (absolute-filled), and the initials stay the
accessible name. */
.avatar__img { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; object-fit: cover; }
/* Decorative-palette avatars — one per accent swatch, each with its own
readable ink. Use for colour-coded identity (per-org / per-user) instead
of hardcoding hex. Rotates with the brand colour + Palette character. */
.avatar--a1 { background: var(--k-accent-1); color: var(--k-accent-1-ink); }
.avatar--a2 { background: var(--k-accent-2); color: var(--k-accent-2-ink); }
.avatar--a3 { background: var(--k-accent-3); color: var(--k-accent-3-ink); }
.avatar--a4 { background: var(--k-accent-4); color: var(--k-accent-4-ink); }
.avatar--a5 { background: var(--k-accent-5); color: var(--k-accent-5-ink); }
.avatar--a6 { background: var(--k-accent-6); color: var(--k-accent-6-ink); }
/* Gradient placeholder — square media tile (cover art, category, preload).
.ph--g1..g6 pull the 6 decorative gradient pairs. */
.ph { border-radius: var(--k-radius-md); background: var(--k-fill); }
.ph--g1 { background: var(--k-grad-1); }
.ph--g2 { background: var(--k-grad-2); }
.ph--g3 { background: var(--k-grad-3); }
.ph--g4 { background: var(--k-grad-4); }
.ph--g5 { background: var(--k-grad-5); }
.ph--g6 { background: var(--k-grad-6); }
/* Group: stacked avatars with negative margin + ring border to separate.
Industry convention (Slack/Linear/GitHub/Notion): stacked avatars never
show status dots — the next avatar's overlap always covers the dot's
bottom-right corner. For status communication use the count label
("5 online") or a non-stacked horizontal list with gap. */
.avatar-group {
display: inline-flex;
align-items: center;
padding-left: var(--k-s-6);
}
.avatar-group > .avatar {
margin-left: calc(var(--k-s-6) * -1);
box-shadow: 0 0 0 2.5px var(--k-surface);
}
.avatar-group .avatar__status { display: none; }
.avatar-group__more {
font-size: var(--k-type-eyebrow);
color: var(--k-fg-muted);
margin-left: var(--k-s-10);
}
/* Online/offline status dot at bottom-right */
.avatar__status {
position: absolute;
bottom: -1px;
right: -1px;
width: var(--k-dot);
height: var(--k-dot);
border-radius: 50%;
box-shadow: 0 0 0 2px var(--k-surface);
}
.avatar__status--online { background: var(--k-success); }
.avatar__status--away { background: var(--k-warning); }
.avatar__status--offline { background: var(--k-fg-faint); }