Avatar

( User / Profile / Image )

Displays a user profile image that degrades gracefully to coloured initials, with an optional presence dot.

Live preview and source code for Avatar

Ana RuizPNDev MehtaKF
LNOHSneha KulkarniRB
ARDMKFLN+2

A profile picture that falls back to coloured initials when there is no image or the image fails to load, with an optional presence dot and an AvatarGroup for stacked user rows. The fallback colour is derived from the name, so the same person keeps the same tint on every render instead of flickering between random ones. It renders a <span> with inline styles and a plain <img>, with no dependencies beyond React.

Installation

Copy the source from the Code tab above into your project as Avatar.tsx. It imports nothing but React, so there is no install step, no CSS to load and no config to change.

The file exports two things: Avatar as its default, and AvatarGroup beside it. The group builds on the same component, so keep them in one file.

Usage

Every prop is optional. With no src, it renders initials derived from the name:

Example.tsx
import Avatar, { AvatarGroup } from "./components/Avatar";

export default function Example() {
    return (
        <>
            <Avatar name="Ana Ruiz" src="/ana.jpg" status="online" />
            <AvatarGroup people={[{ name: "Ana Ruiz" }, { name: "Dev Mehta" }]} max={4} />
        </>
    );
}

When to reach for it

A comment thread, an activity feed or a table of members, where most rows have a picture and some do not. The initials fallback means a missing src still renders something deliberate rather than a broken image icon.

A presence list in a chat or dashboard sidebar. The status dot sits at the bottom-right in four states: online, away, busy and offline.

Social proof in a marketing section, using AvatarGroup. It overlaps the first max people and collapses the rest into a +N chip.

When not to

If it is clickable, wrap it rather than using it as the control. This renders a <span> with no focus handling and no keyboard behaviour. Put it inside a <button> or an <a> and let that element carry the label and the focus ring.

If you are rendering hundreds of remote images, this is a bare <img> with no lazy loading attribute and no next/image sizing. Copy the file and swap the <img> for your framework's image component before you ship a long list.

If you need a member roster rather than a summary, AvatarGroup is the wrong shape. It caps at max and hides everyone else behind a count that is not interactive, which is a decoration on top of a real list, not a substitute for one.

Accessibility

When an image renders, alt falls back to name, so a screen reader gets the person rather than a filename. When the fallback renders instead, what is on screen is the initials, and that is what gets read: "MT", not "Mayank Tomar". If the avatar is the only thing identifying the person, put the name in text beside it.

The presence dot carries an aria-label with the status word, but it is a <span> with no role, and a label on a generic element is not reliably announced. Treat the dot as decoration and put the state in text wherever knowing it actually matters.

Props

Every prop the Avatar component accepts, with its type and default value.

Props accepted by the Avatar component
PropTypeDefaultDescription
srcstringImage URL. When omitted or failing to load, initials are shown instead.
altstringAlt text for the image. Falls back to name.
namestringMayank TomarFull name, used for alt text and to derive the initials.
fallbackstringOverrides the initials derived from name.
size"xs" | "sm" | "md" | "lg" | "xl"lgVisual size of the avatar.
shape"circle" | "square"circleCircle or rounded square.
status"online" | "away" | "busy" | "offline" | "none"nonePresence dot rendered at the bottom-right.
ringbooleanfalseDraws a soft ring around the avatar.

Notes

The fallback colour is hashed from fallback || name, so overriding the initials also changes the tint. Passing the same name anywhere in your app always produces the same colour.

Initials come from the first and last word of name, so "Mayank Tomar" becomes "MT" and a single word becomes its first two letters. An empty name renders ?.

className and style land on the outer wrapper, not on the circle that draws the background, so a background passed through style sits behind the avatar rather than replacing its fill.

AvatarGroup renders every avatar with ring on, which is what keeps the overlap readable. Keep overlap at or below 0.25; above that the initials on the covered avatars start to clip.