Avatar

Avatars help recognise people in lists, attendance and headers. Initials are the default, on --color-surface-2 in --color-text-muted; a photo (src) is shown only when the person (or a guardian, for minors) consented to photos (UX guide §12.4).

An avatar is usually decorative because the name is shown right next to it — then it is hidden from assistive tech. When the avatar is the only identification (e.g. the signed-in user in the top bar), pass label, which makes it an image with that name ("Angemeldet als Sandra Keller").

Sizes (design guide §9.3): xs (24 px) inline in text and dense tables, sm (32 px) in dense lists, the top bar and the club switcher, md (40 px) default, lg (64 px) in profile headers.

variant: "club" shows a club logo: square with --radius-md instead of a circle, the logo fitted inside (club switcher, club lists).

Examples

Initials (decorative, next to a name)

Data
render({
  "initials": "LM"
})
Markup
<span class="avatar" aria-hidden="true">LM</span>

Small, standing alone in the top bar

SK
Data
render({
  "initials": "SK",
  "size": "sm",
  "label": "Angemeldet als Sandra Keller"
})
Markup
<span class="avatar" data-size="sm" role="img" aria-label="Angemeldet als Sandra Keller">SK</span>

Extra small, inline

Data
render({
  "initials": "NK",
  "size": "xs"
})
Markup
<span class="avatar" data-size="xs" aria-hidden="true">NK</span>

Photo with consent

Data
render({
  "src": "/media/members/m-1042.jpg",
  "size": "lg",
  "initials": "LM"
})
Markup
<span class="avatar" data-size="lg" aria-hidden="true"><img src="/media/members/m-1042.jpg" alt=""></span>

Club logo

Data
render({
  "src": "/media/clubs/tkd-bern.svg",
  "size": "sm",
  "variant": "club",
  "initials": "TB"
})
Markup
<span class="avatar" data-size="sm" data-variant="club" aria-hidden="true"><img src="/media/clubs/tkd-bern.svg" alt=""></span>

Data contract

What render(data) accepts — validated against this JSON Schema in development and tests. Unknown fields are rejected. The same schema is in components.json.

FieldTypeRequiredDefaultDescription
initialsstringoptional—One to three initials ("LM"). Required unless src is set; also the fallback text.
min 1 chars · max 3 chars
srcstringoptional—Photo URL (only with photo consent). Rendered as <img> filling the circle.
altstringoptional""Alt text of the photo. Leave empty when the name is shown next to the avatar (decorative).
labelstringoptional—Accessible name when the avatar stands alone ("Angemeldet als Sandra Keller"); sets role="img" + aria-label.
size"xs" | "sm" | "md" | "lg"optional"md"xs 24 px, sm 32 px, md 40 px, lg 64 px.
variant"person" | "club"optional"person"person: circle. club: club logo, square with --radius-md.
JSON Schema
{
  "type": "object",
  "additionalProperties": false,
  "required": [],
  "properties": {
    "initials": {
      "type": "string",
      "minLength": 1,
      "maxLength": 3,
      "description": "One to three initials (\"LM\"). Required unless `src` is set; also the fallback text."
    },
    "src": {
      "type": "string",
      "description": "Photo URL (only with photo consent). Rendered as `<img>` filling the circle."
    },
    "alt": {
      "type": "string",
      "default": "",
      "description": "Alt text of the photo. Leave empty when the name is shown next to the avatar (decorative)."
    },
    "label": {
      "type": "string",
      "description": "Accessible name when the avatar stands alone (\"Angemeldet als Sandra Keller\"); sets `role=\"img\"` + `aria-label`."
    },
    "size": {
      "type": "string",
      "enum": [
        "xs",
        "sm",
        "md",
        "lg"
      ],
      "default": "md",
      "description": "`xs` 24 px, `sm` 32 px, `md` 40 px, `lg` 64 px."
    },
    "variant": {
      "type": "string",
      "enum": [
        "person",
        "club"
      ],
      "default": "person",
      "description": "`person`: circle. `club`: club logo, square with `--radius-md`."
    }
  }
}

Markup & states

Root: span.avatar — usable without render() by writing the markup directly.

Attributes

AttributeValuesDefaultDescription
data-sizexs | sm | lg(none = md, 40 px)Size: 24 / 32 / 64 px.
data-variantclub(none = person)Club logo: --radius-md corners instead of a circle.
aria-hidden="true"——Decorative avatar (no label, and no alt on a photo).
role="img" aria-labeltext—Standalone avatar with label.

Parts

PartDescription
imgPhoto, object-fit: cover.

CSS custom properties

PropertyDefaultDescription
--avatar-size2.5remDiameter; set by data-size, can be overridden for special layouts.

Accessibility

  • Decorative by default (aria-hidden) because the name is shown next to it; avoids "LM Lea Müller" being read twice.
  • Standalone avatars need label; then the image is announced with that name.
  • Initials use --color-text-muted on --color-surface-2, verified for contrast in both themes.

Guidance

DoFall back to initials whenever a photo is missing or not consented.
DoUse first-name + initial for minors on shared screens.
Don'tDon't show photos of minors without guardian consent.
Don'tDon't use avatars as the only way to tell people apart in lists — always show the name.

Related: List · App shell