Dec 24, 2024

Custom Avatar component in svelte

Svelte

Some UI libraries provides Avatar component, that works like- if the provided url is not valid (error on fetching, null | undefined), then it shows a fallback thingy like a text or an icon (whatever you configure).

So what would you do if you ain't using anything like that? maybe just your own component library?
Let's make something like that using svelte magics.

#. Approach

Okay, so first we need the props right? we just need a src and a class as props.
src- image/avatar url (optional)
class- if you need to add classes to element (optional)

avatar.svelte
<script lang="ts"> import { cn } from '$lib/functions/classnames'; type Props = { src?: string | null; class?: string; }; let { src, class: klass }: Props = $props(); </script>

#. Implementation

Now what we gonna do is something more real. we need to check the given src if its valid or not, then we render accordingly.

So we will create an Image object and try to load it with given url and listen for success/failure events. These should be done before the final rendering, so that we can avoid FOUC.

avatar.svelte
<script lang="ts"> // props and stuff let valid_src = $state(false); $effect.pre(() => { if (!src) { valid_src = false; return; } // create img instance const img = new Image(); img.onload = () => (valid_src = true); img.onerror = () => (valid_src = false); img.src = src; }); </script>

Codes inside $effect.pre will get executed before the DOM updates, so that we will get a stable valid_src state.
Now the final part is just to render according to state.

avatar.svelte
<div class={cn( klass, 'grid place-items-center overflow-hidden bg-neutral' )} > {#if valid_src} <img {src} alt="" /> {:else} <!-- whatever you want as a fallback --> {/if} </div>

#. Usage

There you go!
now we can use it like:

svelte
<!-- with src and class --> <Avatar src={quiblet.avatar} class="rounded-full" /> <!-- for just fallback --> <Avatar class="hope-you-like-it" />

#. Helpful links