import { Avatar, AvatarFallback } from '@vega-ui/react';
<Avatar size='lg'><AvatarFallback>JD</AvatarFallback></Avatar>- Browser support
- Widely available
- Chrome 111
- Edge 111
- Firefox 113
- Safari 15.4
- Safari on iOS 15.4
- Bundle size
- Oklab and OkLCh — comes from the design tokens
- aspect-ratio
- :where()
Summary
Avatar renders a user or entity representation with support for image, fallback, and icon content. It is the identity-display primitive for one person or entity, not a generic decorative circle.
Imports
import {
Avatar,
AvatarImage,
AvatarFallback,
AvatarIcon,
type AvatarProps,
type AvatarSize,
type AvatarVariant,
} from '@vega-ui/react';Exported Types
AvatarPropsAvatarImagePropsAvatarFallbackPropsAvatarIconPropsAvatarSizeAvatarVariant
Minimal Composition
import { Avatar, AvatarFallback, AvatarImage } from '@vega-ui/react';
const portrait = (hue: number) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' fill='hsl(${hue} 60% 82%)'/><circle cx='32' cy='25' r='11' fill='hsl(${hue} 35% 42%)'/><path d='M12 64c1-13 9-21 20-21s19 8 20 21z' fill='hsl(${hue} 35% 42%)'/></svg>`)}`;
const photo = portrait(210);
export default function MinimalComposition() {
return (
<Avatar role='img' aria-label='Jane Doe'>
<AvatarImage src={photo} alt='' />
<AvatarFallback>JD</AvatarFallback>
</Avatar>Required Parts
Avatar: root surface
Optional Parts
AvatarImage: image contentAvatarFallback: text fallbackAvatarIcon: icon fallback
Composition Order
AvatarAvatarImageAvatarFallbackorAvatarIcon
Variants
- Sizes:
2xs,xs,sm,md,lg,xl,2xl - Variants:
primary,secondary - Content variants: image, fallback initials, icon
Edge Cases
- Always provide meaningful
alttext for informative avatar images. - Include fallback content for missing or slow-loading images.
- Very small sizes need short fallback text to avoid overflow.
- Decide explicitly whether the avatar is informative identity content or purely decorative context in each usage.
Common Mistakes
- Rendering an avatar image without fallback.
- Using decorative avatars without deciding whether they should be announced.
- Letting fallback initials overflow in small sizes.
Examples
Basic
Basic: member list with photos and initials
The name is already visible next to each avatar, so the avatar is decorative: aria-hidden on the root and alt='' on the image. Members without a photo get initials, and a deactivated member uses variant='secondary'.
import { Avatar, AvatarFallback, AvatarImage, Text } from '@vega-ui/react';
const portrait = (hue: number) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' fill='hsl(${hue} 60% 82%)'/><circle cx='32' cy='25' r='11' fill='hsl(${hue} 35% 42%)'/><path d='M12 64c1-13 9-21 20-21s19 8 20 21z' fill='hsl(${hue} 35% 42%)'/></svg>`)}`;
const members = [
{ name: 'Maria Chen', email: 'maria@northwind.io', initials: 'MC', photo: portrait(210), active: true },
{ name: 'Omar Haddad', email: 'omar@northwind.io', initials: 'OH', photo: portrait(28), active: true },
{ name: 'Lena Fischer', email: 'lena@northwind.io', initials: 'LF', photo: '', active: true },
{ name: 'Tom Becker', email: 'tom@northwind.io', initials: 'TB', photo: '', active: false },
];
export default function MemberList() {Basic: bots, teams and organizations
AvatarIcon stands in for entities that have no face or initials. variant='secondary' keeps them visually apart from people.
import { Avatar, AvatarIcon, Text } from '@vega-ui/react';
import { Bot, Building2, Users } from '@vega-ui/icons';
export default function GenericEntities() {
return (
<ul style={{ listStyle: 'none', margin: 0, padding: 0, display: 'grid', gap: 'var(--spacing-6)', width: '100%' }}>
<li style={{ display: 'flex', alignItems: 'center', gap: 'var(--spacing-6)' }}>
<Avatar size='sm' variant='secondary' aria-hidden='true'>
<AvatarIcon><Bot /></AvatarIcon>
</Avatar>
<Text size={3}>Release bot merged 3 pull requests</Text>
</li>Form/Integration
Form/Integration: profile photo upload with preview
A native file input feeds an object URL into AvatarImage for an instant preview; the URL is revoked when it changes. On submit the file is read from FormData, and reset brings back the initials.
import { ChangeEvent, FormEvent, useEffect, useRef, useState } from 'react';
import { Avatar, AvatarFallback, AvatarImage, Button, Text } from '@vega-ui/react';
export default function PhotoUpload() {
const inputRef = useRef<HTMLInputElement>(null);
const [preview, setPreview] = useState('');
const [result, setResult] = useState('');
useEffect(() => {
if (preview === '') return;
return () => URL.revokeObjectURL(preview);
}, [preview]);Layout/Overlay
Layout/Overlay: comment thread with long text
The avatar is top-aligned with multi-line comments. In a flex row it can be squeezed by long text, so it gets flex-shrink: 0, and the text column gets min-width: 0 with overflow-wrap: anywhere for the long URL.
import { Avatar, AvatarFallback, AvatarImage, Text } from '@vega-ui/react';
const portrait = (hue: number) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' fill='hsl(${hue} 60% 82%)'/><circle cx='32' cy='25' r='11' fill='hsl(${hue} 35% 42%)'/><path d='M12 64c1-13 9-21 20-21s19 8 20 21z' fill='hsl(${hue} 35% 42%)'/></svg>`)}`;
const comments = [
{
id: 1,
author: 'Maria Chen',
initials: 'MC',
photo: portrait(210),
time: '10:24',
text: 'The retry policy should back off exponentially, otherwise a failing endpoint gets hammered every few seconds and we fill the queue with duplicate deliveries for the same event.',Error
Error: image that fails to load
AvatarImage stays hidden until it loads. When it fails, the initials from AvatarFallback show through, or fallbackSrc is tried first if it is set. Each avatar is named once with role='img' and aria-label, so the initials are not read as a second name.
import { Avatar, AvatarFallback, AvatarImage, Text } from '@vega-ui/react';
const portrait = (hue: number) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' fill='hsl(${hue} 60% 82%)'/><circle cx='32' cy='25' r='11' fill='hsl(${hue} 35% 42%)'/><path d='M12 64c1-13 9-21 20-21s19 8 20 21z' fill='hsl(${hue} 35% 42%)'/></svg>`)}`;
const photo = portrait(150);
const placeholder = portrait(220);
const broken = 'data:image/png;base64,broken';
const cases = [
{ label: 'Image loads', name: 'Priya Nair', initials: 'PN', src: photo, fallbackSrc: undefined },
{ label: 'Image fails → initials', name: 'Diego Alvarez', initials: 'DA', src: broken, fallbackSrc: undefined },
{ label: 'Image fails → fallbackSrc', name: 'Sara Lindqvist', initials: 'SL', src: broken, fallbackSrc: placeholder },Edge
Edge: initials from real-world names
Initials are derived from the first and last word, with a single word giving two letters and an empty name falling back to an icon. Array.from keeps non-Latin and accented letters intact, and long names are truncated next to the avatar.
import { Avatar, AvatarFallback, AvatarIcon, Text } from '@vega-ui/react';
import { User } from '@vega-ui/icons';
const getInitials = (name: string) => {
const words = name.trim().split(/\s+/).filter((word) => word !== '');
if (words.length === 0) return '';
if (words.length === 1) return Array.from(words[0]).slice(0, 2).join('').toLocaleUpperCase();
const first = Array.from(words[0])[0];
const last = Array.from(words[words.length - 1])[0];
return `${first}${last}`.toLocaleUpperCase();
};
Anatomy
Overview
Avatar is a compound component because the root, image, fallback, and icon parts cooperate to represent one entity through a prioritized content model.
Required Parts
Avatar
Required. Owns size and variant styling.
Optional Parts
AvatarImage
Optional primary image content.
AvatarFallback
Optional text fallback, often initials.
AvatarIcon
Optional icon fallback for generic entity representation.
Composition Order
AvatarAvatarImageAvatarFallbackorAvatarIcon
Valid Composition Patterns
import { Avatar, AvatarFallback, AvatarImage, Text } from '@vega-ui/react';
const portrait = (hue: number) => `data:image/svg+xml,${encodeURIComponent(`<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect width='64' height='64' fill='hsl(${hue} 60% 82%)'/><circle cx='32' cy='25' r='11' fill='hsl(${hue} 35% 42%)'/><path d='M12 64c1-13 9-21 20-21s19 8 20 21z' fill='hsl(${hue} 35% 42%)'/></svg>`)}`;
const members = [
{ name: 'Maria Chen', email: 'maria@northwind.io', initials: 'MC', photo: portrait(210), active: true },
{ name: 'Omar Haddad', email: 'omar@northwind.io', initials: 'OH', photo: portrait(28), active: true },
{ name: 'Lena Fischer', email: 'lena@northwind.io', initials: 'LF', photo: '', active: true },
{ name: 'Tom Becker', email: 'tom@northwind.io', initials: 'TB', photo: '', active: false },
];
export default function MemberList() {Invalid Composition Patterns
Image without any fallback plan
Broken or slow-loading images leave the entity without a stable representation.
Long fallback text in tiny sizes
The avatar becomes visually unstable and harder to scan.