Skip to content

Avatar

Avatar
Thymeleaf source
<sl:avatar label="shadcn">
<sl:avatar-image th:src="@{/users/{id}/photo(id=${user.id})}"/>
<sl:avatar-fallback>CN</sl:avatar-fallback>
</sl:avatar>
Rendered HTML
<span class="avatar" role="img" aria-label="shadcn">
<img class="avatar-image" alt="" src="data:image/jpeg;base64,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">
<span class="avatar-fallback">CN</span>
</span>

Write both parts, as in shadcn/ui: <sl:avatar-image> with the picture’s src or th:src, and <sl:avatar-fallback> with what to show without one, usually initials or an <sl:icon>. The avatar shows the fallback when the image has no src or an empty one. A th:src whose value is null renders an empty src, so a user without a photo needs no th:if:

FallbackA user without a photo gets their initials; th:src with a null value renders an empty src, which shows the fallback.
Thymeleaf source
<sl:avatar label="Jane Doe">
<sl:avatar-image th:src="${user.photoUrl}"/>
<sl:avatar-fallback>JD</sl:avatar-fallback>
</sl:avatar>
<sl:avatar label="Unknown user">
<sl:avatar-fallback><sl:icon name="user"/></sl:avatar-fallback>
</sl:avatar>
Rendered HTML
<span class="avatar" role="img" aria-label="Jane Doe">
<img class="avatar-image" alt="" src="">
<span class="avatar-fallback">JD</span>
</span>
<span class="avatar" role="img" aria-label="Unknown user">
<span class="avatar-fallback">
<svg xmlns="http://www.w3.org/2000/svg" class="icon" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path>
<circle cx="12" cy="7" r="4"></circle>
</svg>
</span>
</span>

Both parts are always rendered, and the stylesheet decides which one shows. The hidden one is also hidden from assistive technology. The image lies over the fallback at the same size, so nothing moves when one replaces the other.

A photo URL that fails to load shows the fallback too: a 404, a URL your Content-Security-Policy’s img-src blocks, a file that is no image, or no network. So does a photo that is still loading, as in shadcn/ui; the picture replaces the fallback once it is there.

Broken imageA photo URL that fails to load (a 404, a URL the Content-Security-Policy blocks, offline) shows the fallback, as does one that is still loading.
Thymeleaf source
<sl:avatar label="Grace Hopper">
<sl:avatar-image th:src="@{/users/{id}/photo(id=${user.id})}"/>
<sl:avatar-fallback>GH</sl:avatar-fallback>
</sl:avatar>
Rendered HTML
<span class="avatar" role="img" aria-label="Grace Hopper">
<img class="avatar-image" alt="" src="data:image/png;base64,AAAA">
<span class="avatar-fallback">GH</span>
</span>

Shadleaf’s script marks each avatar image with data-status="loaded" when its picture has loaded, or data-status="error", and the stylesheet only shows an image that is marked loaded. So a broken image never shows, not even for a moment before the script runs. The script also marks images htmx swaps in, and an image whose src changes later (htmx swapping the attribute, or a script of yours): the fallback shows while the new picture loads.

Your own CSS can use the mark, for instance to fade the picture in:

@media (prefers-reduced-motion: no-preference) {
.avatar-image[data-status='loaded'] {
animation: avatar-fade-in 150ms;
}
}
@keyframes avatar-fade-in {
from { opacity: 0; }
}
  • Without JavaScript, nothing marks the images, so they lie over the fallback as plain images: a picture that loads covers it. One that fails shows the fallback through it in Firefox, which draws nothing for a broken image with an empty alt; Chromium draws its broken-image icon over it.
  • With JavaScript but without Shadleaf’s script (your policy blocks it, say), every avatar shows its fallback.

The script is part of the one in the assets fragment, whatever shadleaf.assets.alpine is: it is not an Alpine component, and works without Alpine on the page. One listener on the document handles every avatar, so a long list of them costs nothing extra.

Sizes
Thymeleaf source
<sl:avatar size="sm" label="Jane Doe"><sl:avatar-fallback>JD</sl:avatar-fallback></sl:avatar>
<sl:avatar label="Jane Doe"><sl:avatar-fallback>JD</sl:avatar-fallback></sl:avatar>
<sl:avatar size="lg" label="Jane Doe"><sl:avatar-fallback>JD</sl:avatar-fallback></sl:avatar>
Rendered HTML
<span class="avatar" data-size="sm" role="img" aria-label="Jane Doe">
<span class="avatar-fallback">JD</span>
</span>
<span class="avatar" role="img" aria-label="Jane Doe">
<span class="avatar-fallback">JD</span>
</span>
<span class="avatar" data-size="lg" role="img" aria-label="Jane Doe">
<span class="avatar-fallback">JD</span>
</span>

An avatar usually sits next to the person’s name, so it is decorative by default and hidden from assistive technology. When there is no name next to it, give it a label: it is then announced as an image with that name, whichever part shows. aria-labelledby, pointing at a name elsewhere on the page, works too.

Next to a nameWithout a label the avatar is decorative; the name beside it is what a screen reader reads.
Thymeleaf source
<sl:avatar><sl:avatar-fallback>JD</sl:avatar-fallback></sl:avatar>
<span>Jane Doe</span>
Rendered HTML
<span class="avatar" aria-hidden="true">
<span class="avatar-fallback">JD</span>
</span>
<span>Jane Doe</span>
  • A delay before the fallback shows (Radix’s delayMs): the fallback shows at once while a photo loads. A photo from the browser’s cache is there before the first paint, so it does not flash.
  • A loading status event (Radix’s onLoadingStatusChange): read data-status on the image instead.
AttributeValuesDefaultDescription
sizesm default lgdefaultSize of the avatar.
labelstring—The person's name, for an avatar with no name next to it. It is then announced as an image with that name; without it the avatar is hidden from assistive technology.

Every prop can also be set from an expression: th:size="${...}". Any other attribute passes through to the rendered element, and class is appended.

sl:avatar-image declares no props; every attribute passes through.

sl:avatar-fallback declares no props; every attribute passes through.