Angular Avatar Component | ng-hub-ui-avatar
Angular avatar component with initials, fallback images, presence badges and CSS variables for reusable user identity interfaces.
Last updated Sep 6, 2026
Overview
Why teams search for this library
Choose this Angular avatar component when you need resilient user identity UI with fallbacks, initials, multiple image providers and design-system friendly styling hooks.
Install
npm install ng-hub-ui-avatarJump to
Ideal for
- user menus
- team lists
- activity feeds
- profile cards
About avatar
ng-hub-ui-avatar helps Angular applications display users consistently across menus, profile cards and collaborative interfaces. It covers the common edge cases such as missing images, initials generation, status indicators and shared sizing rules.
Feature guides
Avatar Sources
Resolve avatars from social profiles, custom images, name initials or a custom value, with automatic fallback.
Examples:
Facebook Profile
Facebook Profile
Gravatar
Gravatar
GitHub Profile
GitHub Profile
Custom Image Source
Custom Image Source
Name Initials
Name Initials
Value Display
Value Display
Fallback System
Gracefully degrade through every configured source until a meaningful representation is shown.
Examples:
Fallback System
Fallback System
Showing GitHub source (Facebook ID invalid)
Sizing
Control avatar dimensions, the text-to-size ratio and how many initials are rendered.
Examples:
Custom Size
Custom Size
Text Size Ratio
Text Size Ratio
Initials Size Limit
Initials Size Limit
Styling
Shape, corner radius, colours, borders and arbitrary inline styles — all driven by inputs and CSS variables.
Examples:
Round Avatar
Round Avatar
Corner Radius
Corner Radius
Background & Foreground Color
Background & Foreground Color
--hub-avatar-bg-color ([autoColor]="false")Border Color
Border Color
Custom Styles
Custom Styles
Interactivity
React to user interaction with the avatar click event.
Examples:
Click Event Handler
Click Event Handler
Groups & badge
Stack avatars into a group, and overlay a corner badge — a presence dot or a labelled count — coloured by the semantic palette.
Examples:
Avatar Group Display
Avatar Group Display
Badge (dot & count)
Badge (dot & count)
Custom content
Project any icon, inline SVG, image or emoji inside the avatar. It is centered, padded and clipped to the avatar shape, sized agnostically (font icons scale, SVG/images fill) and themed with the regular bgColor / fgColor inputs.
Examples:
Custom content (icons, SVG)
Custom content (icons, SVG)
Key features
Recent changes
Version 22.10.0 - 9/6/26, 12:00 AM
added: Source is part of the public API. The interface that types the clickOnAvatar payload lived only inside the package, so nobody could name the type of their own handler: the choice was any or a hand-copied duplicate that drifts the moment the real one changes. It is a type, so re-exporting it from the entry point costs nothing at runtime.
changed: clickOnAvatar emits Source | null, not Source. The payload was read from a cursor into the fallback list, and that cursor legitimately sits outside it: at -1 until something resolves (an avatar drawn from projected content alone never leaves it) and past the last entry once every source has failed. Clicking in either state handed the consumer undefined through an output that promised a Source, so a handler reading $event.sourceType threw. The absence is now declared instead of leaked and the click still fires; a handler typed (source: Source) has to widen. See BREAKING_CHANGES.md.
changed: The hub-avatar component runs on OnPush. It was the last component in the family still checked on every tick of the application, so a consumer who put an avatar inside an OnPush tree paid for that check and got nothing from it. What the template reads is derived from the inputs, so it marks the view on its own, which is what made the strategy safe to switch.
changed: The avatar is derived from its inputs instead of patched from SimpleChanges. The fallback chain was rebuilt by hand in ngOnChanges, one entry added or removed per changed property, and everything it produced (the resolved picture, the initials, their inline styles) was parked in mutable fields. The chain is a function of the source inputs, so it is computed from them now; the cursor that walks it is linked to it, and what gets painted derives from wherever that cursor sits. The ChangeDetectorRef went with it, because the template reads signals and those mark the view on their own, and dependencies now arrive through inject(). The render state the component used to expose as public fields is now internal. See BREAKING_CHANGES.md.
fixed: Clearing the last source input now clears the avatar. Unsetting name (or src, or any other source) dropped the source from the fallback chain and stopped there: with nothing left to resolve, nothing repainted, and the initials or the picture of the value that had just been removed stayed on screen until some other source arrived. A list rendering avatars for a selection would keep showing the person who had just been deselected.
fixed: The avatar image is named after the person, not after the URL it came from. The alt fell back to the resolved source, so a Gravatar, Facebook or custom picture without an explicit alt made a screen reader read the whole address aloud, and an image resolved asynchronously (GitHub) shipped with no alt at all or with the address a previous source had left behind. The accessible name now comes from alt when given, from name otherwise, and stays empty when there is neither, because an avatar nobody named is decorative and silence beats a URL.
fixed: The manifest now exports the stylesheet paths the documentation teaches. The tarball has always carried styles/index.scss and styles/mixins/_avatar-theme.scss, but the generated exports map listed only the package entry point, so anything under styles/ was formally private. The Angular CLI happens not to notice, since its Sass integration falls back to resolving the package root and joins the rest of the path by hand, yet every resolver that honours the map (webpack's sass-loader, dart-sass's pkg: importer) refuses @use 'ng-hub-ui-avatar/styles' outright. Declaring ./styles and ./styles/mixins/avatar-theme makes the published surface match what the README, the docs page and BREAKING_CHANGES.md tell consumers to write, and aligns the package with ng-hub-ui-ds, which already lists its stylesheet subpaths. Packaging metadata only, with no code, no types and no styles change.
Version 22.9.3 - 9/1/26, 12:00 AM
changed: The homepage in the manifest points at this library's own documentation page rather than at the site root. It is the link a registry shows beside the package and the one a reader clicks from it, and landing on a front page they then have to search is a worse answer than landing on the reference for the package they were already looking at. Metadata only — no code, no types, no styles change, and nothing a consumer imports is affected.
Version 22.9.2 - 8/18/26, 12:00 AM
changed: The README now says what the remote sources cost. Gravatar, GitHub and Facebook were documented as sources resolved over HTTP, which stops one sentence short of the part a consumer has to decide on: those requests leave the visitor's browser, so the third party sees their IP address, and Gravatar also receives a hash of the email address passed to it — enough to correlate a person across every site using it. Nothing changed in the code; the alternative — custom image, initials or text — never leaves your own origin.
Version 22.9.1 - 8/8/26, 12:00 AM
fixed: Documentation links now point at the canonical localized URLs. The README linked to https://hubui.dev/<path> with no locale prefix and no trailing slash, and both forms are 301-redirected, so every reader arriving from npm or GitHub landed on a redirect instead of the canonical page.
Version 22.9.0 - 7/28/26, 12:00 AM
changed: Accent resolution now imports the canonical resolveHubAccent from ng-hub-ui-utils. The private copy under src/lib/shared/resolve-hub-accent.ts has been deleted in favour of the single, tested implementation shared family-wide. Behaviour is identical (the copy had not diverged): a bareword resolves to var(--hub-sys-color-<name>, <name>), a literal colour passes through unchanged, an empty value yields null.
added: NEW peer dependency: ng-hub-ui-utils >=22.7.0. Consumers must have ng-hub-ui-utils installed alongside this library (it is where resolveHubAccent lives). Users installing via ng add ng-hub-ui get it automatically; manual installs need npm i ng-hub-ui-utils.
Version 22.8.0 - 7/28/26, 12:00 AM
added: interactive input: exposes role=button, focusability and Enter/Space activation for avatars that bind (clickOnAvatar) — the click target used to be mouse-only.
Version 22.7.0 - 7/7/26, 12:00 AM
changed: BREAKING (packaging): the SCSS ships at ng-hub-ui-avatar/styles. The theming mixin now builds to dist/avatar/styles/... instead of dist/avatar/src/lib/styles/..., so @use 'ng-hub-ui-avatar/styles' resolves; any @use that reached into src/lib/styles has to be updated.
changed: badgeColor accepts ANY colour. On top of the built-in semantic accents it now takes a registered custom accent and a literal colour (#ff0000, rgb(), oklch(), a CSS named colour): a bareword becomes var(--hub-sys-color-<name>, <name>), a literal is used as is. The single --hub-avatar-accent slot derives the rest of the family, so the built-in colours are unchanged.
changed: Internal: host bindings moved from the @HostBinding / @HostListener decorators to the host metadata object, as the Angular style guide prescribes. No public API or behaviour change.
Version 22.6.0 - 7/7/26, 12:00 AM
added: autoColor input — set [autoColor]="false" on an initials avatar to suppress the inline hash background so it can be themed via the --hub-avatar-bg-color CSS variable (no !important). Defaults to true; an explicit bgColor still wins.
Version 22.5.0 - 6/30/26, 12:00 AM
added: Standalone AvatarComponent — import it directly (no NgModule) and configure with the new provideAvatar() environment provider.
deprecated: AvatarModule / AvatarModule.forRoot() — kept for backward compatibility (now re-exporting the standalone component); use AvatarComponent + provideAvatar() instead.
Version 22.3.0 - 6/26/26, 12:00 AM
changed: BREAKING: the presence-only status input is replaced by a general badge overlay. badge (bare) or [badge]="true" renders a dot, badge="4k" a labelled pill, null or absent nothing; the colour comes from the semantic badgeColor input, so presence is expressed through it (online → success, away → warning, busy → danger, offline → secondary). HubAvatarStatus is renamed HubAvatarBadgeColor and the --hub-avatar-status-* tokens --hub-avatar-badge-*. See BREAKING_CHANGES.md.
added: Semantic colour variants for the avatar and its badge, generated in one loop: a coloured-circle avatar per semantic colour (class="hub-avatar--success") and the matching badgeColor. The hub-avatar-color-variants($colors) mixin emits both in your own CSS, for the eight semantic colours or for your own map.