---
title: "Avatars and identity"
description: "The smallest images in the product, and the ones most likely to assign an identity nobody chose. Defaults, initials, and why a silhouette is not neutral."
url: "https://opsinjs.pensievelabs.org/foundations/imagery/avatars-and-identity"
source: "https://opsinjs.pensievelabs.org/foundations/imagery/avatars-and-identity.md"
section: "Foundations"
kind: "foundation"
reviewed: "2026-09-20"
reviewer: "engineering"
aliases: ["initials avatar", "identity image", "default avatar"]
---

> Elements written as `<PascalCase … />` below are opsinjs documentation
> components. Their attributes are the content: the values they render are
> generated from `tokens/*.json` and `registry/catalogue.ts` and are
> published separately at https://opsinjs.pensievelabs.org/r/index.json and under the Reference
> section.
> Nothing is missing from this page. The data simply does not live in
> the prose.

<PageTemplate kind="foundation" />

## Overview [#overview]

An avatar is a 32-point circle and it is the single most common place a product
assigns somebody an identity. Every default answers a question the reader was not
asked: what colour is your skin, what shape is your body, are you a man or a
woman, are you a person or a patient.

The commonest defaults get it wrong in predictable ways. A grey silhouette of a
head and shoulders is not neutral. It is a specific hairstyle and a specific
build, and it reads as male to most people. An illustrated default with a skin
tone assigns one. A random cartoon assigns a personality.

<NotBuiltYet />

The position opsinjs takes is that the default should carry no bodily information
at all, and that the reader may replace it with something that does. There is a
second question underneath: whether the product needs an avatar in the first
place, and on most screens of a single-user health app it does not.

## How it works [#how-it-works]

**The ladder of defaults**, in order of preference:

1. **No avatar.** In a single-user health product, most screens are about the
   reader and do not need to identify them. An avatar in the corner of every
   screen is chrome that costs space and answers nothing.
2. **Initials on a neutral surface.** Derived from the name the reader gave,
   carrying no bodily information, legible at small sizes, and correct for
   everybody. This is the opsinjs default.
3. **An abstract mark.** A geometric shape or pattern, deterministically derived
   from an identifier. Acceptable where initials do not work, and it must be
   genuinely abstract rather than a stylised person.
4. **A photograph or image the reader has chosen.** Always available, never
   required.

**A silhouette is not on the ladder.** It is a depicted body with a hairstyle, a
neck and a jawline, and there is no version of it that is not somebody.

**Initials are harder than they look.** Names do not reliably split into two
Latin initials: mononyms, names with particles, names in scripts where an
"initial" is not a meaningful unit, names longer than the space allows. Take the
first grapheme cluster of the name as the reader wrote it and never the first
byte, which mangles anything outside ASCII. Fall back to the abstract mark
rather than to nothing.

**Avatar colour comes from the neutral roles or the chart ramp**, deterministically
derived from an identifier. A person is not a health category, so avatar colour
may not come from the category palette, and it certainly may not come from the
status palette.

**A named clinician is a different case.** Where a real person is shown, their
photograph is theirs, consent applies, and their name is present in text beside
it. See [Photography](./photography.mdx).

## Using it [#using-it]

**Ask whether the avatar is doing anything.** On a shared or multi-profile
surface, it distinguishes people and earns its place. On a single-user results
screen it is decoration in the most expensive location on the page.

<DoDont>
  <DoDont.Do>
    Initials on a neutral surface, derived from the name the reader typed, with
    their full name beside it in text and an option to add a photograph.
  </DoDont.Do>

  <DoDont.Dont>
    A grey head-and-shoulders silhouette with no name. It has assigned a body, it
    identifies nobody, and it is doing less work than two letters would.
  </DoDont.Dont>
</DoDont>

**Never derive an avatar from health data.** Not from a status, not from a
category, not from a score. A person is not their reading, and an avatar that
changes colour when a value crosses a threshold has put somebody's clinical status
in the corner of every screen where anyone standing behind them can see it.

**Never derive one from inferred demographics.** Guessing gender from a name to
pick a silhouette is wrong often, and wrong in a way that is hurtful in a health
context. See
[Ask users for: sex and gender](../../patterns/ask-users-for/sex-and-gender.mdx).

**Do not make an avatar the only identifier.** In a multi-profile product, the
name is always present. Two family members with the same initials and similar
photographs is a route to logging a reading against the wrong person.

**Keep it out of the way of the reading.** An avatar in a header is fine; an
avatar beside a value competes with it.

## Tokens [#tokens]

Avatars consume the shape scale and the neutral colour roles or the chart ramp
for the derived surface. A circular avatar takes `full` and a square one takes
a radius rung. The type scale's value roles are explicitly *not* used, since
initials are letters.

<NoDataYet script="scripts/build-tokens.mts" />

## Accessibility impact [#accessibility-impact]

* **An avatar's alternative text is the person's name**, not "avatar" and not a
  description of the image. Where the name is already adjacent in text, the image
  is decorative and hidden.
* **Initials must not be the only way to tell people apart.** Two profiles with
  the same initials are indistinguishable to anybody relying on the avatar, which
  in a health product means a reading logged against the wrong person.
* **Derived colours must meet the contrast floor** against the initials they carry,
  in both themes. A deterministic hue is only acceptable if every possible output
  passes, which is why the derivation uses a checked ramp rather than a hash of
  the name mapped onto arbitrary colours.
* **Avatars scale with text**, like any other element carrying letters. Initials
  clipped at 1.3× is a small failure that lands on exactly the readers most likely
  to be distinguishing profiles.
* **An avatar that encodes health state is a privacy failure**, visible to anybody
  who can see the screen. See
  [On-screen privacy](../../health/on-screen-privacy.mdx).

## Related [#related]

* [Skin-tone representation](./skin-tone-representation.mdx) explains why a
  default with a skin tone is not a neutral choice.
* [On-screen privacy](../../health/on-screen-privacy.mdx) says what may be
  visible on a screen somebody else can see.
* [Inclusive content](../../content/inclusive-content.mdx) covers names, titles
  and how to refer to the reader.
