Circular user avatar with automatic image-fallback to initials.
Follows the shadcn/ui Avatar anatomy: a composable set of sub-components
that work together to display a profile image with a graceful fallback.
The fallback mechanism is powered by an inline onerror attribute on the
<img> tag — no JavaScript hook is required.
Sub-components
| Component | Element | Purpose |
|---|---|---|
avatar/1 | <span> | Circular clipping container with configurable size |
avatar_image/1 | <img> | Profile image; hides itself and reveals fallback on error |
avatar_fallback/1 | <span> | Initials or custom content shown when image is absent |
avatar_group/1 | <div> | Overlapping stack of avatars with negative margin |
Sizes
| Value | Dimensions | Tailwind classes |
|---|---|---|
"sm" | 24 × 24 px | h-6 w-6 |
"default" | 40 × 40 px | h-10 w-10 |
"lg" | 56 × 56 px | h-14 w-14 |
"xl" | 72 × 72 px | h-18 w-18 |
Image with automatic fallback
The most common pattern. When the image URL is valid, the photo is shown.
When the image fails to load (broken URL, network error, 404), the
onerror handler hides the <img> and reveals avatar_fallback/1:
<.avatar>
<.avatar_image src={@user.avatar_url} alt={@user.name} />
<.avatar_fallback name={@user.name} />
</.avatar>Fallback only (no image available)
When you know ahead of time that there is no image — for example when the
user has not uploaded one yet — omit avatar_image/1:
<.avatar size="lg">
<.avatar_fallback name="Jane Smith" />
</.avatar>Icon placeholder
Supply a custom inner block to avatar_fallback/1 instead of using the
:name prop:
<.avatar>
<.avatar_fallback>
<.icon name="user" size={:xs} />
</.avatar_fallback>
</.avatar>Team member list with AvatarGroup
Use avatar_group/1 to render an overlapping cluster of avatars, common
in "assigned to" or "members" widgets. Apply ring-2 ring-background to
individual avatars to create a visible separation between overlapping items:
<%!-- Shows up to 4 avatars then a +N overflow badge --%>
<div class="flex items-center gap-2">
<.avatar_group>
<%= for member <- Enum.take(@team.members, 4) do %>
<.avatar class="ring-2 ring-background" size="sm">
<.avatar_image src={member.avatar_url} alt={member.name} />
<.avatar_fallback name={member.name} />
</.avatar>
<% end %>
</.avatar_group>
<%= if length(@team.members) > 4 do %>
<span class="text-sm text-muted-foreground">
+{length(@team.members) - 4} more
</span>
<% end %>
</div>Comment thread with avatars
<%= for comment <- @comments do %>
<div class="flex gap-3">
<.avatar size="sm">
<.avatar_image src={comment.author.avatar_url} alt={comment.author.name} />
<.avatar_fallback name={comment.author.name} />
</.avatar>
<div>
<p class="text-sm font-medium">{comment.author.name}</p>
<p class="text-sm text-muted-foreground">{comment.body}</p>
</div>
</div>
<% end %>How the onerror fallback works
The avatar_image/1 component attaches an inline onerror JavaScript
handler directly to the <img> element:
onerror="this.style.display='none';
var fb=this.parentElement.querySelector('[data-avatar-fallback]');
if(fb)fb.style.display='flex';"When the browser fails to load the image source it fires the onerror
event synchronously. The handler:
- Hides the
<img>(display: none). - Queries the parent for a
[data-avatar-fallback]sibling. - Reveals it by setting
display: flex.
avatar_fallback/1 carries data-avatar-fallback to serve as the target.
This keeps the mechanism entirely CSS/HTML — no Phoenix hook needed.
Summary
Functions
Renders a circular avatar container.
Renders the avatar fallback displayed when no image is available or loading fails.
Renders the avatar image with an automatic fallback on load error.
Functions
Renders a circular avatar container.
The container is a <span> with overflow-hidden rounded-full so any
child — whether an image or initials fallback — is always clipped to a
perfect circle regardless of the source aspect ratio.
Example
<.avatar size="lg">
<.avatar_image src="/avatars/jane.jpg" alt="Jane Smith" />
<.avatar_fallback name="Jane Smith" />
</.avatar>Attributes
size(:string) - Avatar size. One of"sm"(24px),"default"(40px),"lg"(56px),"xl"(72px). Defaults to"default". Must be one of"sm","default","lg", or"xl".label(:string) - Accessible label (aria-label). Use for standalone avatars that convey meaning. Defaults tonil.class(:string) - Additional CSS classes merged viacn/1. Useful for addingring-2 ring-backgroundin avatar groups. Defaults tonil.- Global attributes are accepted. HTML attributes forwarded to the root
<span>element.
Slots
inner_block(required) -avatar_image/1and/oravatar_fallback/1sub-components.
Renders the avatar fallback displayed when no image is available or loading fails.
There are two ways to supply content:
:nameattribute — pass the user's full name; up to two initials are extracted and uppercased automatically ("Jane Smith"→"JS").Inner block — provide any content (e.g. an icon). When an inner block is present,
:nameis ignored.
The element carries data-avatar-fallback so that avatar_image/1's
onerror handler can locate and reveal it after an image load failure.
Examples
<%!-- Auto initials --%>
<.avatar_fallback name="Carlos Mendoza" />
<%!-- Custom icon --%>
<.avatar_fallback>
<.icon name="user" size={:xs} />
</.avatar_fallback>Attributes
name(:string) - Full name from which up to two initials are derived."Jane Smith"→"JS","Alice"→"A". Ignored when an inner block is provided. Defaults tonil.class(:string) - Additional CSS classes merged viacn/1. Defaults tonil.- Global attributes are accepted. HTML attributes forwarded to the root
<span>element.
Slots
inner_block- Custom fallback content. When provided, overrides the:nameinitials. Useful for icon placeholders.
Renders the avatar image with an automatic fallback on load error.
When the image loads successfully, it fills the avatar container using
object-cover to maintain the circular crop without distortion.
When the image fails to load (broken URL, 404, network error), the
inline onerror handler:
- Hides this
<img>element. - Finds and reveals the sibling
avatar_fallback/1(identified bydata-avatar-fallback).
This happens synchronously in the browser — no LiveView round-trip needed.
Example
<.avatar_image src={@user.photo_url} alt={@user.name} loading="lazy" />Attributes
src(:string) (required) - The image URL. When the URL fails to load, theavatar_fallback/1sibling is revealed automatically.alt(:string) - Accessible alt text. Use the user's full name for proper screen reader support. Defaults to"".class(:string) - Additional CSS classes merged viacn/1. Defaults tonil.- Global attributes are accepted. HTML attributes forwarded to the
<img>element (e.g.loading="lazy").