Avatar
hc-avatar is applied to either an <img> for a photo avatar or
to a <span> for an initials fallback when no image is available.
Both share the same circular surface, sizes, and shape variants.
Image avatars
Section titled “Image avatars”<img class="hc-avatar" src="/users/ada.jpg" alt="Ada Lovelace"><img class="hc-avatar" src="/users/john.jpg" alt="John Smith">The component sets object-fit: cover and overflow: hidden so
images of any aspect ratio render as a centred square crop. (The preview
above uses inline placeholder images; point src at a real photo.)
Initials fallback
Section titled “Initials fallback”When no image is available, render a <span> instead. Use
aria-label to carry the full name; the visible initials should be
short (1-2 characters) and unique enough to identify the user
within a group.
<span class="hc-avatar" aria-label="Ada Lovelace">AL</span>Image fallback
Section titled “Image fallback”When a photo might be missing, wrap the image and an initials fallback
in a single .hc-avatar. The installAvatar() behavior watches the
image’s native load / error events and sets data-state on the
wrapper so the fallback appears automatically when the image fails.
Plain initials and a known-good image need no JavaScript — only this
auto-fallback does:
import { installAvatar } from '@hypermedia-components/core';installAvatar(); // idempotent; returns an uninstallerThe zero-config @hypermedia-components/core/behaviors entry installs it
automatically.
<span class="hc-avatar" role="img" aria-label="Ada Lovelace"> <img class="hc-avatar__image" src="/users/ada.jpg" alt=""> <span class="hc-avatar__fallback" aria-hidden="true">AL</span></span>The wrapper carries the accessible name (role="img" + aria-label); the
image is decorative (alt="") and the fallback is aria-hidden because it
duplicates that name visually.
States
Section titled “States”installAvatar() writes one of these to data-state on the wrapper, so you
can style each phase:
data-state | Meaning |
|---|---|
loading | The image is fetching; the fallback shows so the slot is never empty. |
pending | Fetching, but data-delay is set — the fallback stays hidden for that window to avoid a flash (see below). |
loaded | The image decoded; the fallback is hidden. |
error | The image failed (or has no src); the fallback shows and the broken image is removed. |
Avoiding a flash (data-delay)
Section titled “Avoiding a flash (data-delay)”On a fast connection the image often arrives in a few milliseconds, so
showing the initials first would flash. Set data-delay="<ms>" to hold the
fallback hidden for that window — if the image loads first, the fallback
never appears; otherwise it reveals once the delay elapses.
<span class="hc-avatar" role="img" aria-label="Ada Lovelace" data-delay="500"> <img class="hc-avatar__image" src="/users/ada.jpg" alt=""> <span class="hc-avatar__fallback" aria-hidden="true">AL</span></span>Without JavaScript
Section titled “Without JavaScript”The pattern is progressive: the image overlays the fallback, so a
successful load covers the initials even with installAvatar() absent. The
trade-off is that a broken image is not removed without JS — the browser’s
broken-image indicator may show over the fallback. If you can detect a
missing image server-side, render the <span class="hc-avatar">…</span>
initials form directly instead.
data-size accepts xs, sm, md (default), lg, and xl.
<span class="hc-avatar" data-size="xs" aria-label="Jane Smith">JS</span><span class="hc-avatar" data-size="sm" aria-label="Jane Smith">JS</span><span class="hc-avatar" aria-label="Jane Smith">JS</span><span class="hc-avatar" data-size="lg" aria-label="Jane Smith">JS</span><span class="hc-avatar" data-size="xl" aria-label="Jane Smith">JS</span>data-shape="square" rounds the corners to a square preset
instead of a full circle.
<span class="hc-avatar" aria-label="Jane Smith">JS</span><span class="hc-avatar" aria-label="Jane Smith" data-shape="square">JS</span>Wrap a row of avatars in .hc-avatar-group to overlap them — each
avatar after the first gets a negative margin pull-back and a ring
matching the page background so the overlap reads cleanly.
<div class="hc-avatar-group"> <span class="hc-avatar" aria-label="Ada">A</span> <span class="hc-avatar" aria-label="Beatrice">B</span> <span class="hc-avatar" aria-label="Catalina">C</span> <span class="hc-avatar" aria-label="Dorothée">D</span></div>Accessibility
Section titled “Accessibility”- For
<img class="hc-avatar">, always supply meaningfulalttext — typically the user’s full name. - For initials fallbacks, the visible text is short and visual.
Use
aria-labelto give screen readers the full name; otherwise the user is announced as just “JS” which is rarely useful. - For purely decorative avatars (e.g. a thumbnail next to a name
that is already announced), set
aria-hidden="true"on the avatar to avoid double announcement.
Theming tokens
Section titled “Theming tokens”Component tokens (in component.tokens.json):
| Token path | Purpose |
|---|---|
avatar.size | Default dimension. |
avatar.radius / square-radius | Circle vs square corner radius. |
avatar.bg / fg / border | Fallback surface colors. |
avatar.font-size / font-weight | Initials text styling. |
avatar.xs.* / sm.* / lg.* / xl.* | Dedicated size overrides. |
CSS variables
Section titled “CSS variables”Show the generated CSS variables
--hc-avatar-size | -radius | -square-radius--hc-avatar-bg | -fg | -border--hc-avatar-font-size | -font-weight--hc-avatar-xs-size | -xs-font-size--hc-avatar-sm-size | -sm-font-size--hc-avatar-lg-size | -lg-font-size--hc-avatar-xl-size | -xl-font-sizeRelated
Section titled “Related”- Badge — small status pill, sometimes placed on an avatar.