Skip to main content

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

PropTypeDefaultDescription
size"sm" | "md" | "lg""md"Avatar size
color"default" | "accent" | "success" | "warning" | "danger""default"Fallback color theme
variant"default" | "soft""default"Visual style variant
classstring-Additional CSS classes

Avatar.Image Props

PropTypeDefaultDescription
srcstring-Image source URL
altstring-Alternative text for the image
classstring-Additional CSS classes

The image only mounts once it has loaded (Kobalte Image); until then the fallback renders.

Avatar.Fallback Props

PropTypeDefaultDescription
delayMsnumber-Delay before showing fallback (prevents flash)
color"default" | "accent" | "success" | "warning" | "danger"-Override color from parent
classstring-Additional CSS classes

Differences from HeroUI React

  • Built on Kobalte's Image primitive instead of Radix Avatar — same loading/fallback semantics.
  • Avatar.Image doesn't forward srcSet/sizes/loading/crossOrigin handling through a preloader the way Radix does; standard img attributes pass through to the element once mounted.
  • The React render prop is replaced by Kobalte's as prop.

Last updated: 7/19/26, 3:27 AM

HeroUI SolidUnofficial SolidJS port of HeroUI v3, built on Kobalte and @heroui/styles