Avatar
Overview
The Avatar component represents a person or entity as a compact image.
It falls back
automatically from a photo (src) to initials (from name/initials) to a custom icon, and
finally to a generic default icon — so you never have to hand-roll the broken-image or
missing-photo case.
Import
import { Avatar } from '@allxsmith/bestax-bulma';
Usage
Photo with Automatic Fallback
A working photo renders as an image; if the src fails to load, Avatar swaps to initials
derived from name automatically — no broken-image icon.
<Avatars spaced> <Avatar src="https://github.com/allxsmith.png" name="Al Smith" size="64x64" /> <Avatar src="https://example.invalid/missing.jpg" name="Grace Hopper" size="64x64" /> </Avatars>
Initials
With no src, initials render on a deterministic auto background color derived from name.
<Avatars spaced> <Avatar name="Ada Lovelace" /> <Avatar name="Grace Hopper" /> <Avatar name="Katherine Johnson" /> </Avatars>
Icon Fallback
Pass an icon to control the final fallback when there is no photo, name, or initials.
<Avatar icon={<Icon name="user" />} color="info" shape="rounded" />
Shapes
The shape prop switches between a circle, a rounded square, and a plain square.
<Avatars spaced> <Avatar name="Circle" shape="circle" /> <Avatar name="Rounded" shape="rounded" /> <Avatar name="Square" shape="square" /> </Avatars>
Sizes
Preset sizes mirror Image's fixed-size list; a number renders a pixel size.
<Avatars spaced> <Avatar name="Ada Lovelace" size="24x24" /> <Avatar name="Ada Lovelace" size="32x32" /> <Avatar name="Ada Lovelace" size="48x48" /> <Avatar name="Ada Lovelace" size="64x64" /> <Avatar name="Ada Lovelace" size={20} /> </Avatars>
Clickable Avatar
Set href to render the avatar as a link (or pass as for a custom element).
<Avatar name="Ada Lovelace" href="https://bestax.io" />
Forwarding Props to the Image
imageProps is spread onto the underlying <img> — handy for native attributes like
loading, crossOrigin, or referrerPolicy. A custom onError is chained before the
automatic initials/icon fallback runs.
<Avatar src="https://github.com/allxsmith.png" name="Al Smith" size="64x64" imageProps={{ loading: 'lazy' }} />
Forwarded ref
Avatar forwards a ref to its root element — the <figure>, or the <a> that an href selects — not to the inner <img>.
function example() { const avatarRef = React.useRef(null); const [tag, setTag] = React.useState(null); return ( <> <Avatar ref={avatarRef} name="Ada Lovelace" size="64x64" /> <Button mt="3" onClick={() => setTag(avatarRef.current?.tagName)}> Read the tag from its ref </Button> <p>Rendered element: {tag ?? '—'}</p> </> ); }
Accessibility
- Image avatars use
alt(falling back toname) for their accessible name. - Initials/icon avatars expose
role="img"andaria-label(fromalt/name) — unless rendered as a link or button, where the native link/button role andaria-labelare used instead. A custom component passed toascounts as interactive, since a router link takestorather than this component'shref. If yours renders something that really is just a picture, say so withrole="img"and it's treated as one —alt=""included. A truthyaria-hiddensays it too, and so dorole="presentation"androle="none", though ARIA's own conflict resolution drops those two whenever the avatar still carries a name — preferrole="img". A role claiming the opposite, such as"button", doesn't, and neither does anhref. - Decorative avatars: pass an explicit
alt=""when the avatar repeats information already visible next to it (e.g. beside the author's name in a comment row). The image stays decorative and an initials/icon avatar is skipped entirely (aria-hidden), avoiding double-speak. The opt-out never applies to a link/button avatar — an interactive element always keeps an accessible name (fromname, or a generic"Avatar"fallback) — and a custom component passed toascounts as one until it says otherwise, soalt=""on a custom wrapper needs that signal next to it. - A link/button avatar with no
alt/name(e.g. an API that returns only a photo URL) still gets anaria-labelfallback rather than rendering a nameless control. as="button"defaults totype="button", so a clickable avatar inside a form doesn't submit it.- The default fallback icon is
aria-hidden.
Related Components
Avatars: An overlapping group ofAvatars with a "+N" surplus bubble.Badge: A status/count indicator that overlays anAvatar(or any element).Image: Bulma's fixed-ratio image container.- Helper Props: Bulma helper props for spacing, color, etc.
Additional Resources
Props
| Prop | Type | Default | Description |
|---|---|---|---|
as | React.ElementType | — | Element/component to render as. Defaults to 'a' when href is set, else 'figure'. This also decides whether the avatar is treated as interactive, which is what keeps role="img" and the alt="" decorative opt-out off a link or button. A custom component counts — a router link takes to rather than this component's href, so its own props cannot say — while 'a', 'button', and a custom element given an href count for the reason they read. If your custom component renders something that really is just a picture, say so with role="img" and it is treated as one, alt="" included. A truthy aria-hidden says it too, and so do role="presentation" and role="none" — though ARIA's own conflict resolution drops those two whenever the avatar still carries a name, so prefer role="img". A role claiming the opposite, such as "button", says nothing here, and neither does an href: that settles it on its own. A genuine 'a'/'button'/href avatar keeps its accessible name either way. |
className | string | — | Additional CSS classes to apply. |
src | string | — | Image URL. On load error (or if absent), falls back to initials, then icon. |
alt | string | — | Alternate text for the image (used for the accessible name in every render mode). An explicit alt="" marks a non-interactive avatar as decorative. A link or button avatar is never decorative — it keeps an accessible name — and a custom component passed to as counts as one unless it states otherwise, so alt="" on a custom wrapper needs that signal alongside it. as documents which props carry it. |
name | string | — | Derives initials and a deterministic background color when no src is shown. |
initials | string | — | Explicit initials override (else derived from name). |
icon | React.ReactNode | — | Final fallback, rendered when there is no src, name, or initials. |
size | '16x16' | '24x24' | '32x32' | '48x48' | '64x64' | '96x96' | '128x128' | number | — | Preset size, or a pixel size when a number. |
shape | 'circle' | 'rounded' | 'square' | 'circle' | Avatar shape. Default 'circle'. |
color | AvatarColor | — | Background color for initials/icon avatars (else auto-derived from name). |
href | string | — | When set, renders the avatar as a link: an <a> unless as names the element itself. An as target declaring its own href supersedes this one, and its type and its requiredness are what apply. |
target | string | — | Anchor target — forwarded only when rendering a link (an a or a custom as component), and superseded by the target's own declaration the way href is. |
rel | string | — | Anchor rel — forwarded only when rendering a link (an a or a custom as component), and superseded by the target's own declaration the way href is. |
imageProps | React.ImgHTMLAttributes<HTMLImageElement> | — | Extra props forwarded to the underlying <img> (e.g. loading, crossOrigin); its onError is chained before the fallback fires. |
style | React.CSSProperties | — | Inline styles, merged after the size style. |
ref | PolymorphicRef<React.ElementType> | — | Ref forwarded to the element as renders, typed from as: the DOM node for an intrinsic tag, or whatever handle a custom component exposes. |
... | Remaining props of the element or component selected by as (default <figure>) and Bulma helper props | — | See Helper Props |
Types:
AvatarColor:'primary'|'link'|'info'|'success'|'warning'|'danger'|'black'|'dark'|'light'|'white'— Valid color values for the Avatar component.
CSS & Sass Variables
Avatar registers these variables on its own .avatar element. Override them there (or via className) — a value set on an ancestor is only inherited, and loses to the component-level declaration. See Theme.
| CSS Variable | Sass Variable | Default |
|---|---|---|
--bulma-avatar-size | $avatar-size | 48px |
--bulma-avatar-background | $avatar-background | var(--bulma-background) |
--bulma-avatar-color | $avatar-color | var(--bulma-text) |
--bulma-avatar-weight | $avatar-weight | var(--bulma-weight-semibold) |
--bulma-avatar-rounded-radius | $avatar-rounded-radius | var(--bulma-radius-large) |