Display user profile images with customizable fallback content
Import
import { Avatar } from "heroui-solid";Usage
JDBJR
import { Avatar } from "heroui-solid"
export function Basic() {
return (
<div class="flex items-center gap-4">
<Avatar>
<Avatar.Image
alt="John Doe"
src="https://img.heroui.chat/image/avatar?w=400&h=400&u=3"
/>
<Avatar.Fallback>JD</Avatar.Fallback>
</Avatar>
<Avatar>
<Avatar.Image
alt="Blue"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg"
/>
<Avatar.Fallback>B</Avatar.Fallback>
</Avatar>
<Avatar>
<Avatar.Fallback>JR</Avatar.Fallback>
</Avatar>
</div>
)
}Anatomy
Import the Avatar component and access all parts using dot notation.
import { Avatar } from "heroui-solid";
export default () => (
<Avatar>
<Avatar.Image />
<Avatar.Fallback />
</Avatar>
);Sizes
SMMDLG
import { Avatar } from "heroui-solid"
export function Sizes() {
return (
<div class="flex items-center gap-4">
<Avatar size="sm">
<Avatar.Image
alt="Small Avatar"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg"
/>
<Avatar.Fallback>SM</Avatar.Fallback>
</Avatar>
<Avatar size="md">
<Avatar.Image
alt="Medium Avatar"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/purple.jpg"
/>
<Avatar.Fallback>MD</Avatar.Fallback>
</Avatar>
<Avatar size="lg">
<Avatar.Image
alt="Large Avatar"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/red.jpg"
/>
<Avatar.Fallback>LG</Avatar.Fallback>
</Avatar>
</div>
)
}Colors
DFACSCWRDG
import { Avatar } from "heroui-solid"
export function Colors() {
return (
<div class="flex items-center gap-4">
<Avatar color="default">
<Avatar.Fallback>DF</Avatar.Fallback>
</Avatar>
<Avatar color="accent">
<Avatar.Fallback>AC</Avatar.Fallback>
</Avatar>
<Avatar color="success">
<Avatar.Fallback>SC</Avatar.Fallback>
</Avatar>
<Avatar color="warning">
<Avatar.Fallback>WR</Avatar.Fallback>
</Avatar>
<Avatar color="danger">
<Avatar.Fallback>DG</Avatar.Fallback>
</Avatar>
</div>
)
}Variants
accent
default
success
warning
danger
letter
AG
AG
AG
AG
AG
letter soft
AG
AG
AG
AG
AG
icon
icon soft
img
A
D
S
W
D
import { Person } from "gravity-icons-solid"
import { Avatar, Separator } from "heroui-solid"
import { For, type JSX, Show } from "solid-js"
export function Variants() {
const colors = ["accent", "default", "success", "warning", "danger"] as const
const variants = [
{ content: "AG", label: "letter", type: "letter" },
{ content: "AG", label: "letter soft", type: "letter-soft" },
{ content: () => <Person />, label: "icon", type: "icon" },
{ content: () => <Person />, label: "icon soft", type: "icon-soft" },
{
content: [
"https://img.heroui.chat/image/avatar?w=400&h=400&u=3",
"https://img.heroui.chat/image/avatar?w=400&h=400&u=4",
"https://img.heroui.chat/image/avatar?w=400&h=400&u=5",
"https://img.heroui.chat/image/avatar?w=400&h=400&u=8",
"https://img.heroui.chat/image/avatar?w=400&h=400&u=16"
],
label: "img",
type: "img"
}
] as const
// Elements are real DOM nodes in Solid, so icon content is a factory
// called per cell instead of a shared element like upstream's React JSX.
const renderContent = (content: string | (() => JSX.Element)) =>
typeof content === "function" ? content() : content
return (
<div class="flex flex-col gap-4">
{/* Color labels header */}
<div class="flex items-center gap-3">
<div class="w-24 shrink-0" />
<For each={colors}>
{(color) => (
<div class="flex w-20 shrink-0 items-center justify-center">
<span class="text-xs text-muted capitalize">{color}</span>
</div>
)}
</For>
</div>
<Separator />
{/* Variant rows */}
<For each={variants}>
{(variant) => (
<div class="flex items-center gap-3">
<div class="w-24 shrink-0 text-sm text-muted">{variant.label}</div>
<For each={colors}>
{(color, colorIndex) => (
<div class="flex w-20 shrink-0 items-center justify-center">
<Avatar
color={color}
variant={variant.type.includes("soft") ? "soft" : undefined}
>
<Show
when={variant.type === "img"}
fallback={
<Avatar.Fallback>
{renderContent(
variant.content as string | (() => JSX.Element)
)}
</Avatar.Fallback>
}
>
<Avatar.Image
alt={`Avatar ${color}`}
src={
Array.isArray(variant.content)
? variant.content[colorIndex()]
: ""
}
/>
<Avatar.Fallback>
{color.charAt(0).toUpperCase()}
</Avatar.Fallback>
</Show>
</Avatar>
</div>
)}
</For>
</div>
)}
</For>
</div>
)
}Fallback Content
JDGB
import { Person } from "gravity-icons-solid"
import { Avatar } from "heroui-solid"
export function Fallback() {
return (
<div class="flex items-center gap-4">
{/* Text fallback */}
<Avatar>
<Avatar.Fallback>JD</Avatar.Fallback>
</Avatar>
{/* Icon fallback */}
<Avatar>
<Avatar.Fallback>
<Person />
</Avatar.Fallback>
</Avatar>
{/* Fallback with delay */}
<Avatar>
<Avatar.Image
alt="Delayed Avatar"
src="https://invalid-url-to-show-fallback.com/image.jpg"
/>
<Avatar.Fallback delayMs={600}>NA</Avatar.Fallback>
</Avatar>
{/* Custom styled fallback */}
<Avatar>
<Avatar.Fallback class="border-none bg-gradient-to-br from-pink-500 to-purple-500 text-white">
GB
</Avatar.Fallback>
</Avatar>
</div>
)
}Avatar Group
JDKWECMB
JDKWEC+2
import { Avatar } from "heroui-solid"
import { For } from "solid-js"
const users = [
{
id: 1,
image:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg",
name: "John Doe"
},
{
id: 2,
image:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/green.jpg",
name: "Kate Wilson"
},
{
id: 3,
image:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/purple.jpg",
name: "Emily Chen"
},
{
id: 4,
image:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/orange.jpg",
name: "Michael Brown"
},
{
id: 5,
image:
"https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/red.jpg",
name: "Olivia Davis"
}
]
export function Group() {
return (
<div class="flex flex-col gap-6">
{/* Basic avatar group */}
<div class="flex -space-x-2">
<For each={users.slice(0, 4)}>
{(user) => (
<Avatar class="ring-2 ring-background">
<Avatar.Image alt={user.name} src={user.image} />
<Avatar.Fallback>
{user.name
.split(" ")
.map((n) => n[0])
.join("")}
</Avatar.Fallback>
</Avatar>
)}
</For>
</div>
{/* Avatar group with counter */}
<div class="flex -space-x-2">
<For each={users.slice(0, 3)}>
{(user) => (
<Avatar class="ring-2 ring-background">
<Avatar.Image alt={user.name} src={user.image} />
<Avatar.Fallback>
{user.name
.split(" ")
.map((n) => n[0])
.join("")}
</Avatar.Fallback>
</Avatar>
)}
</For>
<Avatar class="ring-2 ring-background">
<Avatar.Fallback class="text-xs">+{users.length - 3}</Avatar.Fallback>
</Avatar>
</div>
</div>
)
}Custom Styles
XLSQ
GB
ON
import { Avatar } from "heroui-solid"
export function CustomStyles() {
return (
<div class="flex items-center gap-4">
{/* Custom size with Tailwind classes */}
<Avatar class="size-16">
<Avatar.Image
alt="Extra Large"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/blue.jpg"
/>
<Avatar.Fallback>XL</Avatar.Fallback>
</Avatar>
{/* Square avatar */}
<Avatar class="rounded-lg">
<Avatar.Image
alt="Square Avatar"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/purple.jpg"
/>
<Avatar.Fallback class="rounded-lg">SQ</Avatar.Fallback>
</Avatar>
{/* Gradient border */}
<Avatar class="bg-gradient-to-tr from-pink-500 to-yellow-500 p-0.5">
<div class="size-full rounded-full bg-background p-0.5">
<Avatar.Image
alt="Gradient Border"
class="rounded-full"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/red.jpg"
/>
<Avatar.Fallback class="border-none">GB</Avatar.Fallback>
</div>
</Avatar>
{/* Status indicator */}
<div class="relative">
<Avatar>
<Avatar.Image
alt="Online User"
src="https://heroui-assets.nyc3.cdn.digitaloceanspaces.com/avatars/orange.jpg"
/>
<Avatar.Fallback>ON</Avatar.Fallback>
</Avatar>
<span class="absolute right-0 bottom-0 size-3 rounded-full bg-green-500 ring-2 ring-background" />
</div>
</div>
)
}Styling
Passing Tailwind CSS classes
import { Avatar } from "heroui-solid";
function CustomAvatar() {
return (
<Avatar class="size-20">
<Avatar.Image src="..." alt="..." />
<Avatar.Fallback>XL</Avatar.Fallback>
</Avatar>
);
}Customizing the component classes
To customize the Avatar component classes, you can use the @layer components directive.
Learn more.
@layer components {
.avatar {
@apply size-16 border-2 border-primary;
}
.avatar__fallback {
@apply bg-gradient-to-br from-purple-500 to-pink-500;
}
}HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.
CSS Classes
The Avatar component uses these CSS classes (View source styles):
Base Classes
.avatar- Base container with default size (size-10).avatar__image- Image element with aspect-square sizing.avatar__fallback- Fallback container with centered content
Size Modifiers
.avatar--sm- Small avatar (size-8).avatar--md- Medium avatar (default, no additional styles).avatar--lg- Large avatar (size-12)
Variant Modifiers
.avatar--soft- Soft variant with lighter background
Color Modifiers
.avatar__fallback--default- Default text color.avatar__fallback--accent- Accent text color.avatar__fallback--success- Success text color.avatar__fallback--warning- Warning text color.avatar__fallback--danger- Danger text color
API Reference
Avatar Props
| Prop | Type | Default | Description |
|---|---|---|---|
size | "sm" | "md" | "lg" | "md" | Avatar size |
color | "default" | "accent" | "success" | "warning" | "danger" | "default" | Fallback color theme |
variant | "default" | "soft" | "default" | Visual style variant |
class | string | - | Additional CSS classes |
Avatar.Image Props
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | - | Image source URL |
alt | string | - | Alternative text for the image |
class | string | - | Additional CSS classes |
The image only mounts once it has loaded (Kobalte Image); until then the fallback renders.
Avatar.Fallback Props
| Prop | Type | Default | Description |
|---|---|---|---|
delayMs | number | - | Delay before showing fallback (prevents flash) |
color | "default" | "accent" | "success" | "warning" | "danger" | - | Override color from parent |
class | string | - | Additional CSS classes |
Differences from HeroUI React
- Built on Kobalte's Image primitive instead of Radix Avatar — same loading/fallback semantics.
Avatar.Imagedoesn't forwardsrcSet/sizes/loading/crossOriginhandling through a preloader the way Radix does; standardimgattributes pass through to the element once mounted.- The React
renderprop is replaced by Kobalte'sasprop.
Last updated: 7/19/26, 3:27 AM