Avatar

A circular image with a graceful fallback, stackable into groups.

lily
lily
LL

Installation

npx lily-svelte@latest add avatar

Installs the style saved in lily.json. For a new Diamond project, run lily-svelte init --style diamond first.

Usage

<script lang="ts">
	import { Avatar } from '$lib/components/ui/avatar';
</script>
 
<Avatar src="/avatars/lily.png" alt="lily" />

Fallback

When src is missing or fails to load, the fallback is shown instead. Pass a string for initials, or a snippet for anything else.

<Avatar fallback="LL" alt="Levi Laine" />
 
<Avatar alt="Acme Inc.">
	{#snippet fallback()}
		<Icon icon="heroicons:building-office-solid" class="size-1/2" />
	{/snippet}
</Avatar>

With no fallback at all, a neutral placeholder icon is used.

<Avatar alt="Unknown user" />

Images

The avatar is usually the most repeated image on a page, so the image attributes that matter for that are props of their own: srcset, sizes, loading, crossorigin and referrerpolicy.

<Avatar src="/avatars/lily.png" srcset="/avatars/lily.png 1x, /avatars/lily@2x.png 2x" alt="lily" />

loading defaults to lazy. The avatars above the fold — the first row of a member list, the one in the header — should be eager, or they pop in after the page settles.

<Avatar src={user.avatar} loading="eager" alt={user.name} />

For a third-party avatar host, referrerpolicy keeps your URLs out of their logs, and crossorigin is what lets the image be read back from a canvas.

<Avatar src={githubAvatar} referrerpolicy="no-referrer" alt={user.name} />

Everything else you pass lands on the wrapper, not the image.

Sizes

<Avatar size="xs" alt="xs" />
<Avatar size="sm" alt="sm" />
<Avatar alt="default" />
<Avatar size="lg" alt="lg" />
<Avatar size="xl" alt="xl" />

Group

AvatarGroup overlaps its children and rings each one so they stay separable.

lily
LL
MJ
+3
<script lang="ts">
	import { Avatar, AvatarGroup, AvatarGroupCount } from '$lib/components/ui/avatar';
</script>
 
<AvatarGroup>
	<Avatar src="/avatars/lily.png" alt="lily" />
	<Avatar fallback="LL" alt="Levi Laine" />
	<Avatar fallback="MJ" alt="Mia Jung" />
	<AvatarGroupCount>+3</AvatarGroupCount>
</AvatarGroup>

Use spacing to tune the overlap.

<AvatarGroup spacing="tight">...</AvatarGroup>
<AvatarGroup spacing="loose">...</AvatarGroup>

The ring is painted with the --avatar-ring variable, which defaults to the page background. On an elevated surface — inside a card, dialog or popover — point it at the surface instead.

<AvatarGroup class="[--avatar-ring:var(--bg-elevated)]">...</AvatarGroup>

Set size on every avatar and on AvatarGroupCount to keep them aligned.

<AvatarGroup>
	<Avatar size="sm" src="/avatars/lily.png" alt="lily" />
	<Avatar size="sm" fallback="LL" alt="Levi Laine" />
	<AvatarGroupCount size="sm">+3</AvatarGroupCount>
</AvatarGroup>

Badge

AvatarBadge pins a status dot to the avatar and scales itself to the parent's size. It takes its color from whatever class you give it.

lily
lily
LL
<script lang="ts">
	import { Avatar, AvatarBadge } from '$lib/components/ui/avatar';
</script>
 
<Avatar src="/avatars/lily.png" alt="lily">
	<AvatarBadge class="bg-emerald-500" />
</Avatar>

At xs and sm the badge renders as a plain dot — any svg child is hidden, since there is no room for a glyph.

The badge is ringed in the same --avatar-ring colour the group uses, defaulting to the page background. Repoint it when the avatar sits on an elevated surface.

<Avatar src="/avatars/lily.png" alt="lily" class="[--avatar-ring:var(--bg-elevated)]">
	<AvatarBadge class="bg-emerald-500" />
</Avatar>

Built by levish. The source code is available on GitHub.

Quiet by design.