# Avatar

> User images and initials in a circle, with sizes, a status dot and overlapping groups.

Page: https://pico.rusticstack.com/docs/extras/avatar

An avatar is a `<span data-avatar>` that holds an image, initials, or both. The image sits over the initials. If the image fails to load, the initials show. No class is needed.

Load `css/extras/avatar.min.css`, or the whole set from `css/pico.extras.min.css`. See the [overview](/docs/extras/overview).

## Sizes

`sm` is 2rem, the default is 2.5rem, `lg` is 3.5rem and `xl` is 5rem. The initials scale with the circle. Give each avatar `role="img"` and an `aria-label` with the person's name.

**Example: Avatar sizes**

```html
<p>
  <span data-avatar="sm" role="img" aria-label="Ada Lovelace">AL</span>
  <span data-avatar role="img" aria-label="Ada Lovelace">AL</span>
  <span data-avatar="lg" role="img" aria-label="Ada Lovelace">AL</span>
  <span data-avatar="xl" role="img" aria-label="Ada Lovelace">AL</span>
</p>
```

## Image with initials fallback

Put an empty-`alt` image before the initials. The name is already on the wrapper, so the image is decorative. When the image fails, a tiny script removes it so no broken icon is drawn and the initials show. The second avatar below has an image that does not exist.

**Example: Image and fallback**

```html
<p>
  <span data-avatar="lg" role="img" aria-label="Ada Lovelace"
    ><img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 80 80'%3E%3Crect width='80' height='80' fill='%23a14f2a'/%3E%3Ccircle cx='40' cy='32' r='14' fill='%23f3d3b8'/%3E%3Cellipse cx='40' cy='78' rx='26' ry='24' fill='%23f3d3b8'/%3E%3C/svg%3E" alt="" width="56" height="56" />AL</span
  >
  <span data-avatar="lg" role="img" aria-label="Grace Hopper"
    ><img src="/missing/grace.webp" alt="" width="56" height="56" />GH</span
  >
</p>

<script>
  document.querySelectorAll("[data-avatar] > img").forEach((img) => {
    img.addEventListener("error", () => img.remove());
  });
</script>
```

## Status

`data-status` takes `online`, `away`, `busy` or `offline`. The dot is drawn by the wrapper, so no extra element is needed. The shape carries the state as well as the color: solid for online, half filled for away, a bar for busy and hollow for offline. Put the status in the `aria-label` too.

**Example: Status dots**

```html
<p>
  <span data-avatar data-status="online" role="img" aria-label="Ada Lovelace, online">AL</span>
  <span data-avatar data-status="away" role="img" aria-label="Grace Hopper, away">GH</span>
  <span data-avatar data-status="busy" role="img" aria-label="Alan Turing, busy">AT</span>
  <span data-avatar data-status="offline" role="img" aria-label="Edsger Dijkstra, offline">ED</span>
</p>
```

## Group

A `role="group"` with a label, whose children are avatars, overlaps them. A ring in the surface color separates each one. A final `+3` avatar works as an overflow count.

**Example: Avatar group**

```html
<div role="group" aria-label="Project members">
  <span data-avatar role="img" aria-label="Ada Lovelace">AL</span>
  <span data-avatar role="img" aria-label="Grace Hopper">GH</span>
  <span data-avatar role="img" aria-label="Alan Turing">AT</span>
  <span data-avatar role="img" aria-label="3 more people">+3</span>
</div>
```

Form groups are left alone. The group rules apply only when the children are avatars, or links or buttons with an `aria-label` that hold only an avatar.

## Links and menu triggers

An `a`, `button` or `summary` that holds only an avatar and has an `aria-label` loses its button or link chrome. The label is what marks the control as avatar-only, so a button with an avatar and a visible name ("Account") keeps its normal button style. Keyboard focus draws a 3:1 ring on the avatar itself. Visible initials inside a link or button start the accessible name ("AL, Ada Lovelace"), so speech input can say what it sees.

**Example: Avatar links and a menu**

```html
<div role="group" aria-label="Team">
  <a href="#ada" aria-label="Ada Lovelace"
    ><span data-avatar data-status="online" role="img" aria-label="AL, Ada Lovelace, online">AL</span></a
  >
  <a href="#grace" aria-label="Grace Hopper"
    ><span data-avatar role="img" aria-label="GH, Grace Hopper">GH</span></a
  >
</div>

<details class="dropdown">
  <summary aria-label="Account menu">
    <span data-avatar role="img" aria-label="GH, Grace Hopper">GH</span>
  </summary>
  <ul>
    <li><a href="#profile">Profile</a></li>
    <li><a href="#out">Sign out</a></li>
  </ul>
</details>
```

## Accessibility

- `role="img"` and an `aria-label` give the avatar a name. Leave out the label only when a name sits right next to it, and then hide the avatar with `aria-hidden="true"`.
- State the status in the label, because the dot is decorative.
- Initials are isolated from the page direction, so `+3` stays `+3` in right to left text.

## Customization

The status ring takes the color of the surface under it. Inside a card, a card header or footer and a dropdown menu, the ring color is already set to match. On any other colored surface, set `--pico-avatar-ring-color` yourself.

| Variable | Default | Description |
| --- | --- | --- |
| `--pico-avatar-size` | `2.5rem` | Diameter. The sm, lg and xl values set it to 2rem, 3.5rem and 5rem. |
| `--pico-avatar-overlap` | `0.375rem` | How much avatars in a group overlap. |
| `--pico-avatar-background-color` | `var(--pico-secondary-background)` | Fill behind the initials. |
| `--pico-avatar-color` | `var(--pico-secondary-inverse)` | Initials color. |
| `--pico-avatar-ring-color` | `var(--pico-background-color)` | Ring around the status dot and between grouped avatars. |
| `--pico-avatar-status-online-color` | `var(--pico-ins-color)` | Online dot. |
| `--pico-avatar-status-offline-color` | `var(--pico-muted-color)` | Offline dot. |
| `--pico-avatar-status-away-color` |  | Away dot. |
| `--pico-avatar-status-busy-color` | `var(--pico-del-color)` | Busy dot. |

