Avatars
Identity on screen - photos when you have them, deterministic initials and generative art when you don't, plus presence dots, six sizes from 2xs and the stacked team group.
Identity without photos
The placeholder system, from plain to generative: monogram initials, a deterministic colour or gradient hashed from the name, and art - mesh draws a soft gradient orb (initials optional), dither a two-tone pixel blend. Same name, same result, every render. No JavaScript, no dependencies.
<div class="flex flex-wrap items-center justify-center gap-4">
<.avatar name="Sarah Chen" size="lg" />
<.avatar name="Sarah Chen" size="lg" random_color />
<.avatar name="Sarah Chen" size="lg" random_gradient />
<.avatar name="Sarah Chen" size="lg" art="mesh" />
<.avatar name="Sarah Chen" size="lg" art="mesh" initials />
<.avatar name="Sarah Chen" size="lg" art="dither" />
</div>
Rounded for orgs
Circles are the convention for people; shape="rounded" gives orgs, teams and workspaces proportional soft corners instead. Deliberately independent of the radius dial - avatars are identity, not surface.
<div class="flex flex-wrap items-center justify-center gap-4">
<.avatar name="Petal Framework" size="lg" shape="rounded" random_gradient />
<.avatar name="Acme Corp" size="lg" shape="rounded" art="mesh" />
<.avatar name="Initech" size="lg" shape="rounded" art="dither" />
<.avatar name="Globex" size="lg" shape="rounded" random_color />
</div>
Six sizes, four presence states
The size ladder from 2xs to xl - 2xs is for dense rows: a table cell, a compact activity feed - and the status dot: online, busy, away, offline, ringed so it reads against any image or placeholder. Presence works on every avatar form.
<div class="flex flex-col items-center gap-6">
<div class="flex flex-wrap items-end justify-center gap-3">
<.avatar name="Sarah Chen" size="2xs" random_color />
<.avatar name="Sarah Chen" size="xs" random_color />
<.avatar name="Sarah Chen" size="sm" random_color />
<.avatar name="Sarah Chen" size="md" random_color />
<.avatar name="Sarah Chen" size="lg" random_color />
<.avatar name="Sarah Chen" size="xl" random_color />
</div>
<div class="flex flex-wrap items-center justify-center gap-4">
<.avatar name="Amelia Ward" size="md" art="mesh" status="online" />
<.avatar name="Jonah Reyes" size="md" art="mesh" status="busy" />
<.avatar name="Priya Anand" size="md" art="mesh" status="away" />
<.avatar name="Tom Hale" size="md" art="mesh" status="offline" />
</div>
</div>
The team stack
avatar_group overlaps your hosted image URLs into the classic team pile; max caps the row and folds the rest into a +N bubble. shape passes through to every avatar and the bubble. The URLs here are inline SVG stand-ins - swap in real photos and nothing else changes.
<div class="flex flex-col items-center gap-4">
<.avatar_group
size="md"
max={3}
avatars={[
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><rect width='8' height='8' fill='%23f59e0b'/></svg>",
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><rect width='8' height='8' fill='%2310b981'/></svg>",
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><rect width='8' height='8' fill='%236366f1'/></svg>",
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><rect width='8' height='8' fill='%23ec4899'/></svg>",
"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'><rect width='8' height='8' fill='%2306b6d4'/></svg>"
]}
/>
</div>
Properties
| Attribute | Type | Default | Description |
|---|---|---|---|
alt
|
string |
nil
|
alt text for avatar image |
art
|
string |
nil
|
generative art instead of initials: mesh is a soft multi-hue gradient, dither an ordered-dither blend - both hashed from the name, so the same name always draws the same avatar. Pure art by default; the name still labels the avatar for screen readers, and a photo src wins when present
one of: nil, "mesh", "dither"
|
class
|
any |
nil
|
CSS class |
initials
|
boolean |
false
|
mesh only: overlay the monogram on the art as a dark hue-tinted monogram (the mesh reads light, so it always contrasts). Ignored for dither - a discrete pixel pattern never lets text sit cleanly, so dither stays pure art |
name
|
string |
nil
|
name for placeholder initials |
random_color
|
boolean |
false
|
generates a random color for placeholder initials avatar |
random_gradient
|
boolean |
false
|
generates a gradient background for placeholder initials, hashed from the name like random_color - same name, same gradient. Wins over random_color when both are set |
rest
|
global |
||
shape
|
string |
"circle"
|
circle is the convention for people; rounded (proportional soft corners) suits orgs, teams and workspaces. Deliberately independent of the --pc-radius dial - avatars are identity, not surface, and a sharp-cornered theme still wants soft avatars
one of: "circle", "rounded"
|
size
|
string |
"md"
|
one of: "2xs", "xs", "sm", "md", "lg", "xl"
|
src
|
string |
nil
|
hosted avatar URL |
status
|
string |
nil
|
presence dot on the bottom-right corner, ringed to separate from the image
one of: nil, "online", "offline", "busy", "away"
|