React Avatar Examples — Initials, Groups, Status Badges
Copy-paste React Avatar examples — user initials fallback, avatar groups, online status dots, data table cells, and account menu triggers — using Drivn.
An avatar shows up wherever an interface names a person — comment threads, member lists, table rows, the account button in a header. In every one of those places it has the same job: render the profile picture if there is one, and stay recognizable if there is not. Drivn's Avatar is a single component that covers both branches with a conditional render on src.
The prop surface is four items. src is the image URL, alt is the screen-reader text on that image, fallback is the name or initials string, and size picks one of four fixed circles — sm at 32 px, md at 40 px (the default), lg at 48 px, xl at 64 px. When src is missing, the component renders fallback?.slice(0, 2).toUpperCase() inside a bg-muted circle with text-foreground, so initials read correctly in both themes without a className override.
The five patterns below are the ones that keep recurring in production code: an identity block with initials fallback, an overlapping group for team rosters, a presence dot, an avatar cell in a data table, and an avatar as a dropdown trigger. Install with the CLI, then import Avatar from @/components/ui/avatar. For the implementation differences against shadcn/ui, see Drivn vs shadcn/ui Avatar.
User identity with initials fallback
The base pattern is one Avatar with all four props filled in. src points at the picture, alt describes it for screen readers, fallback holds the name, and size sets the circle. The component slices the first two characters off fallback and uppercases them, so fallback="Jane Doe" renders JA and fallback="JD" renders JD — pass whichever field your database already has and skip the string manipulation at the call site.
The fallback branch triggers on falsiness, not on a load error: src={undefined}, src={null}, and src="" all render initials, while a URL that returns 404 still renders a broken <img>. Feeding the raw database column straight into src therefore works without a ternary wrapped around the component. Match the size to the context — lg on a profile header where the picture carries identity, sm in list rows and table cells where it should not push the line height around. Wrap it in a Tooltip when the surrounding layout has no room for the full name.
1 <Avatar 2 src="/user.jpg" 3 alt="Jane Doe" 4 fallback="JD" 5 size="md" 6 /> 7 8 {/* No image — initials render automatically */} 9 <Avatar 10 fallback="Jane Doe" 11 size="md" 12 />
Overlapping avatar group
Team rosters, shared file previews, and "people watching this" indicators often show three to five avatars in an overlapping row. Apply a negative margin-left to each avatar after the first to create the stack effect, and cap the group at a fixed count with a +N overflow label when the list is long.
The outer wrapper needs flex items-center and each Avatar after the first gets -ml-2 or -ml-3 depending on size. Apply a ring-2 ring-background className to each Avatar via the className prop — the ring draws on the background color token, adapting to light and dark themes without hardcoded colors. Combine with a Badge at the end for overflow counts longer than four.
1 const members = [ 2 { src: '/alice.jpg', name: 'Alice' }, 3 { src: '/bob.jpg', name: 'Bob' }, 4 { src: undefined, name: 'Carol Chen' }, 5 { src: '/dave.jpg', name: 'Dave' }, 6 ] 7 const visible = members.slice(0, 3) 8 const overflow = members.length - 3 9 10 <div className="flex items-center"> 11 {visible.map((m) => ( 12 <Avatar 13 key={m.name} 14 src={m.src} 15 alt={m.name} 16 fallback={m.name} 17 size="sm" 18 className="-ml-2 first:ml-0 ring-2 ring-background" 19 /> 20 ))} 21 {overflow > 0 && ( 22 <span className="ml-1 text-sm text-muted-foreground"> 23 +{overflow} 24 </span> 25 )} 26 </div>
Online status indicator
Presence indicators — a green dot for online, grey for offline, yellow for away — are a common need in team tools and chat interfaces. Because Drivn's Avatar has no built-in slot for decorations, the pattern is to wrap the Avatar in a relative container and overlay a positioned <span> for the dot. The border-background class gives the dot a halo that adapts to both light and dark themes.
For screen reader users, include the status in the Avatar's alt text — "Alice (online)" — so the presence is announced without relying on the visual dot. The bottom-0 right-0 position anchors the dot to the bottom-right of the avatar regardless of size, and w-3 h-3 scales visually with md and lg avatar sizes.
1 <div className="relative inline-flex"> 2 <Avatar 3 src="/alice.jpg" 4 alt="Alice (online)" 5 fallback="Alice" 6 size="md" 7 /> 8 <span 9 className={ 10 "absolute bottom-0 right-0 w-3 h-3 rounded-full" 11 + " bg-green-500 border-2 border-background" 12 } 13 title="Online" 14 /> 15 </div>
Avatar inside a data table cell
Data tables that list users almost always want the avatar in the first column alongside the name. Use size="sm" for table rows to keep line height consistent with surrounding text, and wrap the avatar and name in a flex container for alignment.
For tables built with Drivn's DataTable, define the user column with a custom cell renderer that returns the flex container. The size="sm" avatar at 32 px sits flush with the standard table row height. Pass fallback from the user's name field so rows without a profile picture still render a recognizable pair of initials rather than an empty circle.
1 // In your column definition 2 { 3 accessorKey: 'user', 4 header: 'User', 5 cell: ({ row }) => { 6 const user = row.original.user 7 return ( 8 <div className="flex items-center gap-2"> 9 <Avatar 10 src={user.avatarUrl} 11 alt={user.name} 12 fallback={user.name} 13 size="sm" 14 /> 15 <span className="font-medium">{user.name}</span> 16 </div> 17 ) 18 }, 19 }
Install Drivn in one command
Copy the source into your project and own every line. Zero runtime dependencies, pure React + Tailwind.
npx drivn@latest createRequires Node 18+. Works with npm, pnpm, and yarn.
Frequently asked questions
The Drivn Avatar uses a conditional render on the src prop — it shows <img> when src is truthy and the initials span when it is not. A URL that resolves to a 404 is still truthy, so the browser shows a broken image. To add error-based fallback, open src/components/ui/avatar.tsx after install and add a local const [imgError, setImgError] = React.useState(false) state, then pass onError={() => setImgError(true)} to the img element. Render the initials span when either !src or imgError is true.
Yes — wrap the Avatar in a Drivn Tooltip component. Set the content prop to the user's full name and pass the Avatar as a child of Tooltip.Trigger. The Tooltip handles all hover and focus state internally. Use a small Tooltip in dense contexts like data tables and the default size for standalone avatars on profile pages or comment threads.
Pass an empty string as fallback or omit the prop entirely. The component calls fallback?.slice(0, 2).toUpperCase(), which returns undefined when fallback is undefined and an empty string when it is "". Both cases render a circle with no text, styled by the base classes — bg-muted with rounded-full overflow-hidden — so it reads as a neutral placeholder in both themes. To brand that circle instead, pass a className with your own background utility; cn() runs tailwind-merge, so it overrides bg-muted cleanly.
Yes — pass a className that overrides the rounded-full base class. The cn() utility in Drivn uses tailwind-merge, which resolves conflicting border-radius classes automatically. For a rounded square, use className="rounded-lg"; for a sharp square, use className="rounded-none". Combine with a size variant — size="lg" is common for product cards and file thumbnails that use a square avatar pattern.

