# Avatar A circular user icon. Shows a profile photo when a URL is provided, or falls back to text (typically initials) on a neutral background. --- ## Quick example ```csharp // Initials only new Avatar(fallback: "JD") // With a profile photo new Avatar(fallback: "Jane Doe", src: "/avatars/jane.jpg") ``` --- ## All the options ```csharp public Avatar( string fallback, string? src = null, string size = "default") ``` | Parameter | What it does | |---|---| | `fallback` | The text shown when no image is available — typically initials like `"JD"`. Also used as the `alt` attribute on the image for screen readers. | | `src` | URL of the profile photo. If omitted, the fallback is shown. | | `size` | How big the circle is: `"sm"` (32px), `"default"` (40px), `"lg"` (56px), `"xl"` (80px) | --- ## Real-world examples ### Initials in different sizes ```csharp new Avatar(fallback: "SM", size: "sm") // 32×32 — good for compact lists new Avatar(fallback: "JD", size: "default") // 40×40 — standard nav bar new Avatar(fallback: "LG", size: "lg") // 56×56 — profile card header new Avatar(fallback: "XL", size: "xl") // 80×80 — full profile page ``` ### Profile page header ```csharp new Avatar( fallback: user.DisplayName ?? "?", src: user.AvatarUrl, size: "xl") ``` The `fallback` is always required — even with a `src` — because it becomes the `alt` text on the `` tag. ### Overlapping avatar stack (e.g. "3 team members") Wrap multiple avatars in a flex container with negative spacing: ```html
$$Avatar1$$ $$Avatar2$$ $$Avatar3$$
``` --- ## How it works The avatar is a `` clipped to a circle with `rounded-full overflow-hidden`. When a `src` is given, an `` fills the circle using `object-cover` so the photo does not stretch. When there is no `src`, a `` with a muted background shows the fallback text centred inside the circle. The component does not handle broken image URLs. If you need a fallback when an image 404s, add an `onerror` attribute in the surrounding HTML. The Avatar does not extract initials from full names — do that yourself before constructing it. `"Jane Doe"` → `"JD"` is two lines of C# and is better kept in your own code. --- ## Complete page example **`Templates/ProfilePage.htmx`** ```html
$$UserAvatar$$

$$DisplayName$$

$$Email$$

Member since $$JoinDate$$

``` **`Templates/ProfilePage.htmx.cs`** ```csharp namespace Htmx.ApiDemo.Templates; public sealed class ProfilePage : ProfilePageBase { private readonly IHtmxComponent _avatar; private readonly byte[] _displayName; private readonly byte[] _email; private readonly byte[] _joinDate; public ProfilePage(AppUser user) { _avatar = new Components.Avatar( fallback: GetInitials(user.DisplayName), size: "lg"); _displayName = (user.DisplayName ?? "Unknown").ToUtf8Bytes(); _email = user.Email.ToUtf8Bytes(); _joinDate = user.CreatedAt.ToString("MMMM yyyy").ToUtf8Bytes(); } private static string GetInitials(string? name) { if (string.IsNullOrWhiteSpace(name)) return "?"; var parts = name.Split(' ', StringSplitOptions.RemoveEmptyEntries); return parts.Length >= 2 ? $"{parts[0][0]}{parts[^1][0]}" : name[..1].ToUpperInvariant(); } protected override void RenderUserAvatar(HtmxRenderContext ctx) => _avatar.Render(ctx.Next()); protected override void RenderDisplayName(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_displayName); protected override void RenderEmail(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_email); protected override void RenderJoinDate(HtmxRenderContext ctx) => ctx.Writer.WriteUtf8(_joinDate); } ``` **GET handler** ```csharp [Handler] [MapGet("/profile")] public static partial class GetProfileHandler { public record Query(); private static async Task HandleAsync( Query _, HttpContext ctx, MongoDbService db, CancellationToken ct) { var email = ctx.User.FindFirst(ClaimTypes.Email)?.Value ?? ""; var user = await db.FindByNormalizedEmailAsync(email.ToUpperInvariant(), ct); if (user is null) return Results.Redirect("/login"); return await ctx.WriteHtmxPage(new ProfilePage(user), title: "Profile"); } } ```