Kern GitHub

Avatar

Square avatar with image and initials fallback. Alpine is only needed when both `image` and `initials` are provided so `@error` can reveal the fallback.
Requires Alpine.js
Avatar is square by design: circular treatment is reserved for inherently circular controls and counts, while this primitive keeps the system's sharp visual language. Pass meaningful `alt` text unless the person's name is visible next to the avatar; then `alt=""` is correct. When `image` and `initials` are both set, Alpine is used only to reveal the initials fallback on `@error`. The fallback behavior is documented here instead of demoed with a broken image so docs pages stay console-clean.

Image

Abstract portrait for Mira Kern
1{{ avatar_src = 'img/avatar-demo.svg' }}
2{{ partial:components/primitives/avatar image="{avatar_src}" alt="Abstract portrait for Mira Kern" /}}

Initials

Mira Kern Jonas List
1{{ partial:components/primitives/avatar initials="MK" alt="Mira Kern" /}}
2{{ partial:components/primitives/avatar initials="JL" alt="Jonas List" class="bg-secondary text-secondary-foreground" /}}

Sizes

Small avatar Default avatar Large avatar
1{{ partial:components/primitives/avatar initials="SM" alt="Small avatar" size="sm" /}}
2{{ partial:components/primitives/avatar initials="DF" alt="Default avatar" /}}
3{{ partial:components/primitives/avatar initials="LG" alt="Large avatar" size="lg" /}}

Image with fallback

Abstract portrait for Mira Kern
1{{ avatar_src = 'img/avatar-demo.svg' }}
2{{ partial:components/primitives/avatar image="{avatar_src}" alt="Abstract portrait for Mira Kern" initials="MK" size="lg" /}}

Props

Name Type Default Description
image string Image URL or asset path
alt string Image alternative text; use an empty string only when the visible adjacent name already identifies the person
initials string Fallback initials
size string default Size variant: sm|default|lg
class string Additional classes merged via tw_merge (root element only)

Slots

No slots detected.

Source

1{{#
2 @name Avatar
3 @desc Square avatar with image and initials fallback. Alpine is only needed when both `image` and `initials` are provided so `@error` can reveal the fallback.
4 @param image string - Image URL or asset path
5 @param alt string - Image alternative text; use an empty string only when the visible adjacent name already identifies the person
6 @param initials string - Fallback initials
7 @param size string [default] - Size variant: sm|default|lg
8 @param class string - Additional classes merged via tw_merge (root element only)
9#}}
10{{# format-ignore-start #}}
11{{ _size_key = size ?? 'default' }}
12
13{{ _sizes = [
14 'sm' => 'size-8 text-xs',
15 'default' => 'size-10 text-sm',
16 'lg' => 'size-12 text-base',
17] }}
18
19{{ _class_size = _sizes[_size_key] ?? _sizes['default'] }}
20{{# format-ignore-end #}}
21{{ _class = 'border-border bg-muted text-muted-foreground inline-flex shrink-0 items-center justify-center overflow-hidden border font-bold uppercase {_class_size} {class}'
22 | tw_merge }}
23{{ if image && initials }}
24 <span class="{{ _class }}" x-data="{ failed: false }">
25 <img
26 src="{{ image }}"
27 alt="{{ alt }}"
28 class="size-full object-cover"
29 x-show="!failed"
30 @error="failed = true"
31 />
32 <span class="flex size-full items-center justify-center" x-show="failed" style="display: none">
33 <span aria-hidden="true">{{ initials }}</span>
34 <span class="sr-only">{{ alt }}</span>
35 </span>
36 </span>
37{{ elseif image }}
38 <span class="{{ _class }}">
39 <img src="{{ image }}" alt="{{ alt }}" class="size-full object-cover" />
40 </span>
41{{ else }}
42 <span class="{{ _class }}">
43 <span aria-hidden="true">{{ initials }}</span>
44 <span class="sr-only">{{ alt }}</span>
45 </span>
46{{ /if }}

Dependencies

Packages

1composer require marcorieser/tailwind-merge-statamic
2npm install alpinejs