---
title: Avatar
subtitle: An easily stylable avatar component.
description: A high-quality, unstyled React avatar component that is easy to customize.
---

> FineSoft Components documentation. Independent Stencil port; not the official Base UI website.
>
> React API text and `@base-ui/react` examples are upstream references. FineSoft Stencil examples use `finesoft-components`. Do not treat the two packages as interchangeable.

# Avatar

A high-quality, unstyled React avatar component that is easy to customize.

## Demo

### Tailwind

This example shows how to implement the component using Tailwind CSS.

```tsx
/* docs-comparison.tsx */
import { StencilComparison } from 'docs/src/components/StencilComparison';
import ReactAvatar from './react-avatar';
import StencilAvatar from './stencil-avatar';

export default function AvatarComparison() {
  return <StencilComparison component="avatar" react={<ReactAvatar />} stencil={<StencilAvatar />} />;
}
```

```tsx
/* react-avatar.tsx */
import { Avatar } from '@base-ui/react/avatar';

export default function ExampleAvatar() {
  return (
    <div className="flex gap-4">
      <Avatar.Root className="inline-flex size-8 items-center justify-center overflow-hidden rounded-full bg-neutral-200 align-middle text-sm leading-none font-normal text-neutral-950 select-none dark:bg-neutral-800 dark:text-white">
        <Avatar.Image src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80" width="48" height="48" className="size-full object-cover" />
        <Avatar.Fallback delay={600} className="flex size-full items-center justify-center text-sm">
          LT
        </Avatar.Fallback>
      </Avatar.Root>
      <Avatar.Root className="inline-flex size-8 items-center justify-center overflow-hidden rounded-full bg-neutral-200 align-middle text-sm leading-none font-normal text-neutral-950 select-none dark:bg-neutral-800 dark:text-white">
        LT
      </Avatar.Root>
    </div>
  );
}
```

```tsx
/* stencil-avatar.tsx */
export default function StencilAvatar() {
  return (
    <div className="flex gap-4">
      <fs-avatar-root className="[&::part(avatar)]:box-border [&::part(avatar)]:border-0 [&::part(avatar)]:border-solid [&::part(avatar)]:inline-flex [&::part(avatar)]:size-8 [&::part(avatar)]:items-center [&::part(avatar)]:justify-center [&::part(avatar)]:overflow-hidden [&::part(avatar)]:rounded-full [&::part(avatar)]:bg-neutral-200 [&::part(avatar)]:align-middle [&::part(avatar)]:text-sm [&::part(avatar)]:leading-none [&::part(avatar)]:font-normal [&::part(avatar)]:text-neutral-950 [&::part(avatar)]:select-none dark:[&::part(avatar)]:bg-neutral-800 dark:[&::part(avatar)]:text-white">
        <fs-avatar-image
          src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80"
          width="48"
          height="48"
          className="[&::part(image)]:box-border [&::part(image)]:border-0 [&::part(image)]:border-solid [&::part(image)]:size-full [&::part(image)]:object-cover [&::part(image)]:block [&::part(image)]:align-middle"
        />
        <fs-avatar-fallback
          delay={600}
          className="[&::part(fallback)]:box-border [&::part(fallback)]:border-0 [&::part(fallback)]:border-solid [&::part(fallback)]:flex [&::part(fallback)]:size-full [&::part(fallback)]:items-center [&::part(fallback)]:justify-center [&::part(fallback)]:text-sm"
        >
          LT
        </fs-avatar-fallback>
      </fs-avatar-root>
      <fs-avatar-root className="[&::part(avatar)]:box-border [&::part(avatar)]:border-0 [&::part(avatar)]:border-solid [&::part(avatar)]:inline-flex [&::part(avatar)]:size-8 [&::part(avatar)]:items-center [&::part(avatar)]:justify-center [&::part(avatar)]:overflow-hidden [&::part(avatar)]:rounded-full [&::part(avatar)]:bg-neutral-200 [&::part(avatar)]:align-middle [&::part(avatar)]:text-sm [&::part(avatar)]:leading-none [&::part(avatar)]:font-normal [&::part(avatar)]:text-neutral-950 [&::part(avatar)]:select-none dark:[&::part(avatar)]:bg-neutral-800 dark:[&::part(avatar)]:text-white">
        LT
      </fs-avatar-root>
    </div>
  );
}
```

### CSS Modules

This example shows how to implement the component using CSS Modules.

```css
/* index.module.css */
.Root {
  display: inline-flex;
  justify-content: center;
  align-items: center;
  vertical-align: middle;
  border-radius: 100%;
  -webkit-user-select: none;
  user-select: none;
  font-weight: 400;
  color: oklch(14.5% 0 0deg);
  background-color: oklch(92.2% 0 0deg);
  font-size: 0.875rem;
  line-height: 1;
  overflow: hidden;
  height: 2rem;
  width: 2rem;

  @media (prefers-color-scheme: dark) {
    color: white;
    background-color: oklch(26.9% 0 0deg);
  }
}

.Image {
  object-fit: cover;
  height: 100%;
  width: 100%;
}

.Fallback {
  align-items: center;
  display: flex;
  justify-content: center;
  height: 100%;
  width: 100%;
  font-size: 0.875rem;
}
```

```tsx
/* docs-comparison.tsx */
import { StencilComparison } from 'docs/src/components/StencilComparison';
import ReactAvatar from './react-avatar';
import StencilAvatar from './stencil-avatar';

export default function AvatarComparison() {
  return <StencilComparison component="avatar" react={<ReactAvatar />} stencil={<StencilAvatar />} />;
}
```

```tsx
/* react-avatar.tsx */
import { Avatar } from '@base-ui/react/avatar';
import styles from './index.module.css';

export default function ExampleAvatar() {
  return (
    <div style={{ display: 'flex', gap: '1rem' }}>
      <Avatar.Root className={styles.Root}>
        <Avatar.Image src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80" width="48" height="48" className={styles.Image} />
        <Avatar.Fallback delay={600} className={styles.Fallback}>
          LT
        </Avatar.Fallback>
      </Avatar.Root>
      <Avatar.Root className={styles.Root}>LT</Avatar.Root>
    </div>
  );
}
```

```tsx
/* stencil-avatar.tsx */
export default function StencilAvatar() {
  return (
    <div style={{ display: 'flex', gap: '1rem' }}>
      <fs-avatar-root>
        <fs-avatar-image src="https://images.unsplash.com/photo-1543610892-0b1f7e6d8ac1?w=128&h=128&dpr=2&q=80" width="48" height="48" />
        <fs-avatar-fallback delay={600}>LT</fs-avatar-fallback>
      </fs-avatar-root>
      <fs-avatar-root>LT</fs-avatar-root>
    </div>
  );
}
```

## Anatomy

Import the component and assemble its parts:

```jsx title="Anatomy"
import { Avatar } from '@base-ui/react/avatar';

<Avatar.Root>
  <Avatar.Image src="" />
  <Avatar.Fallback>LT</Avatar.Fallback>
</Avatar.Root>;
```

## Optimized and lazy-loaded images

By default, `<Avatar.Image>` preloads `src` and renders the image only once it has loaded. This doesn't compose with image optimizers such as `next/image`, which serve a different URL than the raw `src`, or with `loading="lazy"`.

Add the `keepMounted` prop to render the image element right away and let it load in place. Only the image that is actually displayed is requested:

```jsx title="Using next/image"
import Image from 'next/image';

<Avatar.Root>
  <Avatar.Fallback>LT</Avatar.Fallback>
  <Avatar.Image keepMounted render={<Image src="/avatar.png" width={32} height={32} alt="" />} />
</Avatar.Root>;
```

### Stacking

With `keepMounted`, the image and the fallback are both present until the image loads. The image is hidden from assistive technology until then, so the fallback provides the accessible name on its own.

Stack the two in the same box, and place `<Avatar.Image>` after `<Avatar.Fallback>`. Both are positioned, so whichever comes later in the DOM paints on top. The fallback then shows through until the image covers it.

A loading image paints nothing, so the fallback shows through on its own. An image that failed to load paints a broken-image icon on top of it. Hide the image in either state with the `data-loading` and `data-error` attributes:

```css title="Stacked image and fallback"
.Root {
  position: relative;
}

.Image,
.Fallback {
  position: absolute;
  inset: 0;
}

.Image[data-loading],
.Image[data-error] {
  visibility: hidden;
}
```

Avoid `display: none` here: an element without a box never intersects the viewport, so `loading="lazy"` would never fetch the image. `visibility` and `opacity` both keep lazy loading working.

### Server rendering

With `keepMounted`, the image is part of the server-rendered HTML and starts loading before hydration. So is the fallback, which stays visible until hydration resolves the loading status. A cached image is displayed immediately, without an enter animation.

## Stencil theme and styling

The Stencil family uses Shadow DOM and exposes `::part(avatar)`, `::part(image)`, and `::part(fallback)`. The Base UI theme is built in; select `data-fs-theme="base-ui"` on an ancestor to apply the optional theme; ordinary Avatar examples need no component classes. Override the `--fs-avatar-*` variables for size, shape, and colors, or target a part for a custom skin.

Image states are available on both `fs-avatar-image` and its native image. For example, use `fs-avatar-image[data-error]::part(image)` for a failed retained image, and `fs-avatar-image[data-starting-style]::part(image)` for an entrance transition. External `aria-labelledby` and `aria-describedby` references resolve on the native element. Server rendering preserves the three Shadow boundaries and restores initially unmounted image or delayed fallback declarations during hydration.

## API reference

### Root

Displays a user's profile picture, initials, or fallback icon.
Renders a `<span>` element.

**Root Props:**

| Prop      | Type                                                                                      | Default | Description                                                                                                                                                                                   |
| :-------- | :---------------------------------------------------------------------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| className | `string \| ((state: Avatar.Root.State) => string \| undefined)`                           | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                      |
| style     | `React.CSSProperties \| ((state: Avatar.Root.State) => React.CSSProperties \| undefined)` | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                   |
| render    | `ReactElement \| ((props: HTMLProps, state: Avatar.Root.State) => ReactElement)`          | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

### Root.Props

Re-export of [Root](/react/components/avatar.md) props.

### Root.State

```typescript
type AvatarRootState = {
  /** The image loading status. */
  imageLoadingStatus: ImageLoadingStatus;
};
```

### Image

The image to be displayed in the avatar.
Renders an `<img>` element.

**Image Props:**

| Prop                  | Type                                                                                                                                                         | Default | Description                                                                                                                                                                                   |
| :-------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| onLoadingStatusChange | `((status: ImageLoadingStatus) => void)`                                                                                                                     | -       | Callback fired when the loading status changes.                                                                                                                                               |
| className             | `string \| ((state: Avatar.Image.State) => string \| undefined)`                                                                                             | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                      |
| style                 | `React.CSSProperties \| ((state: Avatar.Image.State) => React.CSSProperties \| undefined)`                                                                   | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                   |
| keepMounted           | `boolean`                                                                                                                                                    | `false` | Whether the image element stays mounted and loads in place instead of being preloaded.&#xA;Supports `loading="lazy"` and optimized image components such as `next/image`.                     |
| render                | `ReactElement \| ((props: React.DetailedHTMLProps<React.ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>, state: Avatar.Image.State) => ReactElement)` | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

**Image Data Attributes:**

| Attribute           | Type | Description                                 |
| :------------------ | :--- | :------------------------------------------ |
| data-error          | -    | Present when the image failed to load.      |
| data-loading        | -    | Present while the image is loading.         |
| data-starting-style | -    | Present when the image begins animating in. |
| data-ending-style   | -    | Present when the image is animating out.    |

### Image.Props

Re-export of [Image](/react/components/avatar.md) props.

### Image.State

```typescript
type AvatarImageState = {
  /** The transition status of the component. */
  transitionStatus: TransitionStatus;
  /** The image loading status. */
  imageLoadingStatus: ImageLoadingStatus;
};
```

### Fallback

Rendered when the image fails to load or when no image is provided.
Renders a `<span>` element.

**Fallback Props:**

| Prop      | Type                                                                                          | Default | Description                                                                                                                                                                                   |
| :-------- | :-------------------------------------------------------------------------------------------- | :------ | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| delay     | `number`                                                                                      | `0`     | How long to wait before showing the fallback. Specified in milliseconds.                                                                                                                      |
| className | `string \| ((state: Avatar.Fallback.State) => string \| undefined)`                           | -       | CSS class applied to the element, or a function that&#xA;returns a class based on the component's state.                                                                                      |
| style     | `React.CSSProperties \| ((state: Avatar.Fallback.State) => React.CSSProperties \| undefined)` | -       | Style applied to the element, or a function that&#xA;returns a style object based on the component's state.                                                                                   |
| render    | `ReactElement \| ((props: HTMLProps, state: Avatar.Fallback.State) => ReactElement)`          | -       | Allows you to replace the component's HTML element&#xA;with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |

### Fallback.Props

Re-export of [Fallback](/react/components/avatar.md) props.

### Fallback.State

```typescript
type AvatarFallbackState = {
  /** The image loading status. */
  imageLoadingStatus: ImageLoadingStatus;
};
```

## Additional Types

### ImageLoadingStatus

```typescript
type ImageLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error';
```

## Export Groups

- `Avatar.Root`: `Avatar.Root`, `Avatar.Root.State`, `Avatar.Root.Props`
- `Avatar.Image`: `Avatar.Image`, `Avatar.Image.State`, `Avatar.Image.Props`
- `Avatar.Fallback`: `Avatar.Fallback`, `Avatar.Fallback.State`, `Avatar.Fallback.Props`
- `Default`: `ImageLoadingStatus`, `AvatarRootState`, `AvatarRootProps`, `AvatarImageState`, `AvatarImageProps`, `AvatarFallbackState`, `AvatarFallbackProps`

## Canonical Types

Maps `Canonical`: `Alias` — Use Canonical when its namespace is already imported; otherwise use Alias.

- `Avatar.Root.State`: `AvatarRootState`
- `Avatar.Root.Props`: `AvatarRootProps`
- `Avatar.Image.State`: `AvatarImageState`
- `Avatar.Image.Props`: `AvatarImageProps`
- `Avatar.Fallback.State`: `AvatarFallbackState`
- `Avatar.Fallback.Props`: `AvatarFallbackProps`

[//]: # '@exclude-table-of-contents'

## Additional types
