# Shadcn Avatar

> Free shadcn/ui avatar component for React — a Radix image with a graceful initials fallback. Sizes, an avatar group/stack, status indicators, and square/ringed shapes. The examples official shadcn never shipped.

Source: https://designrevision.com/components/avatar

The **Shadcn Avatar** is the user image — the canonical <a href="https://ui.shadcn.com/docs/components/avatar" rel="nofollow">shadcn/ui</a> avatar built on <a href="https://www.radix-ui.com/primitives/docs/components/avatar" rel="nofollow">Radix</a>, with a **graceful fallback** to initials when the image is missing or still loading. Official ships one demo; the examples below cover the real uses — **groups, status dots, sizes, and shapes**.

## Built on Radix

Avatar wraps <a href="https://www.radix-ui.com/primitives/docs/components/avatar" rel="nofollow">Radix Avatar</a> with three parts:

```tsx
<Avatar>
  <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
  <AvatarFallback>CN</AvatarFallback>
</Avatar>
```

`AvatarImage` renders **only once the image has loaded**; until then — or if it fails — `AvatarFallback` shows. That's the whole point: avatars never break into a busted-image icon. Put initials in the fallback.

## Fallbacks & initials

For users without a photo, skip the image (or let it fail) and the `AvatarFallback` initials fill the circle. Give the fallback a background and text color for **colored initials** (`bg-rose-500 text-white`) — a common pattern for distinguishing people in a list. The Fallbacks example shows plain and colored.

## Sizes & shapes

Size with a className on `Avatar` — the default is `size-8`; use `size-6` … `size-16` (the Sizes example). For a **square** avatar, set `rounded-lg` on the `Avatar` and `AvatarFallback` to override the default `rounded-full`; add `ring-2 ring-offset-2` for a ringed look (the Shape & ring example).

## Avatar groups

A stacked **avatar group** is a flex row with a negative gap so they overlap, plus a ring on each so they separate cleanly:

```tsx
<div className="flex -space-x-2">
  <Avatar className="ring-background ring-2">…</Avatar>
  …
  <Avatar className="ring-background ring-2">
    <AvatarFallback>+3</AvatarFallback>
  </Avatar>
</div>
```

The Avatar group example includes the "+N" overflow.

## Status & context

Pin a **status dot** to the avatar by wrapping it in a `relative` container and absolutely positioning a small ringed `rounded-full` span at the bottom-right — green for online, amber for away, muted for offline (the Status indicator example). In a list or menu, set the avatar beside a name and email (the With name example) — the pattern this gallery now uses in its [Card](/components/card), [Dropdown Menu](/components/dropdown-menu), and [Popover](/components/popover) user examples.

## Accessibility & theming

Give `AvatarImage` a meaningful `alt` (the person's name), or `alt=""` when the name is already shown beside it. Don't rely on the **status dot color alone** — pair it with a label. The avatar reads your design tokens — `--muted` (the fallback background), `--background` (group rings) — so it follows your theme, including dark mode, with no overrides.

## Installation

### avatar

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar
```

**Dependencies:** @radix-ui/react-avatar, utils

**Usage & accessibility:** A Radix avatar — three parts (Avatar, AvatarImage, AvatarFallback). AvatarImage renders only once the image has loaded; until then (or if it fails) AvatarFallback shows — put initials there. Size it with a className on Avatar (default size-8); use rounded-lg for a square avatar, and stack a group with -space-x-* plus a ring. Always give AvatarImage an alt.

```tsx
// components/ui/avatar.tsx
"use client"

import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar"

import { cn } from "@/lib/utils"

function Avatar({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Root>) {
  return (
    <AvatarPrimitive.Root
      data-slot="avatar"
      className={cn(
        "relative flex size-8 shrink-0 overflow-hidden rounded-full",
        className
      )}
      {...props}
    />
  )
}

function AvatarImage({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Image>) {
  return (
    <AvatarPrimitive.Image
      data-slot="avatar-image"
      className={cn("aspect-square size-full", className)}
      {...props}
    />
  )
}

function AvatarFallback({
  className,
  ...props
}: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
  return (
    <AvatarPrimitive.Fallback
      data-slot="avatar-fallback"
      className={cn(
        "bg-muted flex size-full items-center justify-center rounded-full",
        className
      )}
      {...props}
    />
  )
}

export { Avatar, AvatarImage, AvatarFallback }
```

## Examples

### Avatar

The canonical avatar — an image with an initials fallback that shows while it loads or if it fails.

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar-demo-01
```

**Dependencies:** avatar

```tsx
// components/ui/avatar-demo-01.tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"

export default function AvatarDemo01() {
  return (
    <Avatar>
      <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
      <AvatarFallback>CN</AvatarFallback>
    </Avatar>
  )
}
```

---

### Fallbacks

Initials fallbacks for when there is no image — plain and colored.

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar-fallback-01
```

**Dependencies:** avatar

```tsx
// components/ui/avatar-fallback-01.tsx
import { Avatar, AvatarFallback } from "@/components/ui/avatar"

const colored = [
  { initials: "AL", color: "bg-rose-500" },
  { initials: "BC", color: "bg-blue-500" },
  { initials: "CD", color: "bg-emerald-500" },
  { initials: "DE", color: "bg-violet-500" },
]

export default function AvatarFallbackDemo01() {
  return (
    <div className="flex items-center gap-3">
      {/* Plain fallback (shows when there's no image). */}
      <Avatar>
        <AvatarFallback>JD</AvatarFallback>
      </Avatar>
      {/* Colored fallbacks. */}
      {colored.map((person) => (
        <Avatar key={person.initials}>
          <AvatarFallback className={`${person.color} text-white`}>
            {person.initials}
          </AvatarFallback>
        </Avatar>
      ))}
    </div>
  )
}
```

---

### Sizes

Avatars from `size-6` to `size-16` — set the size with a className on `Avatar`.

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar-sizes-01
```

**Dependencies:** avatar

```tsx
// components/ui/avatar-sizes-01.tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"

const sizes = ["size-6", "size-8", "size-10", "size-12", "size-16"]

export default function AvatarSizes01() {
  return (
    <div className="flex items-center gap-4">
      {sizes.map((size) => (
        <Avatar key={size} className={size}>
          <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
          <AvatarFallback>CN</AvatarFallback>
        </Avatar>
      ))}
    </div>
  )
}
```

---

### Avatar group

A stacked group of overlapping avatars (`-space-x` + ring) with a "+N" overflow.

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar-group-01
```

**Dependencies:** avatar

```tsx
// components/ui/avatar-group-01.tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"

const members = [
  { src: "https://github.com/shadcn.png", fallback: "CN" },
  { src: "https://github.com/leerob.png", fallback: "LR" },
  { src: "https://github.com/evilrabbit.png", fallback: "ER" },
  { src: "https://github.com/vercel.png", fallback: "VC" },
]

export default function AvatarGroup01() {
  return (
    <div className="flex -space-x-2">
      {members.map((member, index) => (
        <Avatar key={index} className="ring-background ring-2">
          <AvatarImage src={member.src} alt="" />
          <AvatarFallback>{member.fallback}</AvatarFallback>
        </Avatar>
      ))}
      <Avatar className="ring-background ring-2">
        <AvatarFallback className="text-muted-foreground text-xs">
          +3
        </AvatarFallback>
      </Avatar>
    </div>
  )
}
```

---

### Status indicator

An online / away / offline status dot pinned to the bottom-right of the avatar.

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar-status-01
```

**Dependencies:** avatar

```tsx
// components/ui/avatar-status-01.tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"

const people = [
  { src: "https://github.com/shadcn.png", fallback: "CN", status: "bg-green-500", label: "Online" },
  { src: "https://github.com/leerob.png", fallback: "LR", status: "bg-amber-500", label: "Away" },
  { src: "https://github.com/evilrabbit.png", fallback: "ER", status: "bg-muted-foreground", label: "Offline" },
]

export default function AvatarStatus01() {
  return (
    <div className="flex items-center gap-6">
      {people.map((person, index) => (
        <div key={index} className="relative">
          <Avatar className="size-10">
            <AvatarImage src={person.src} alt="" />
            <AvatarFallback>{person.fallback}</AvatarFallback>
          </Avatar>
          <span
            title={person.label}
            className={`ring-background absolute right-0 bottom-0 size-3 rounded-full ring-2 ${person.status}`}
          />
        </div>
      ))}
    </div>
  )
}
```

---

### Shape & ring

Round (default), square (`rounded-lg`), and a ringed avatar with `ring-offset`.

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar-shapes-01
```

**Dependencies:** avatar

```tsx
// components/ui/avatar-shapes-01.tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"

export default function AvatarShapes01() {
  return (
    <div className="flex items-center gap-6">
      {/* Default round */}
      <Avatar className="size-12">
        <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
      {/* Square (rounded-lg) */}
      <Avatar className="size-12 rounded-lg">
        <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
        <AvatarFallback className="rounded-lg">CN</AvatarFallback>
      </Avatar>
      {/* With a ring */}
      <Avatar className="ring-primary ring-offset-background size-12 ring-2 ring-offset-2">
        <AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
        <AvatarFallback>CN</AvatarFallback>
      </Avatar>
    </div>
  )
}
```

---

### With name

The user-row pattern — an avatar beside a name and email, the second falling back to initials.

**Install:**

```bash
npx shadcn@latest add @designrevision/avatar-detail-01
```

**Dependencies:** avatar

```tsx
// components/ui/avatar-detail-01.tsx
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"

const people = [
  { src: "https://github.com/shadcn.png", name: "shadcn", email: "shadcn@example.com", fallback: "CN" },
  { src: "", name: "Ada Lovelace", email: "ada@example.com", fallback: "AL" },
]

export default function AvatarDetail01() {
  return (
    <div className="grid gap-4">
      {people.map((person, index) => (
        <div key={index} className="flex items-center gap-3">
          <Avatar>
            <AvatarImage src={person.src} alt={person.name} />
            <AvatarFallback>{person.fallback}</AvatarFallback>
          </Avatar>
          <div className="grid gap-0.5">
            <p className="text-sm leading-none font-medium">{person.name}</p>
            <p className="text-muted-foreground text-xs">{person.email}</p>
          </div>
        </div>
      ))}
    </div>
  )
}
```
