SvelteKit Image Fallback Component Pattern
Build a reusable SvelteKit image fallback component using on:error events and fallback.pics placeholder URLs for broken images and missing CMS media fields.
SvelteKit provides a clean way to handle image failures using Svelte's on:error directive on img elements. Combined with a reactive let variable for the src, you can build a drop-in fallback component that handles broken URLs and missing CMS media.
For server-rendered pages, resolve fallback URLs in SvelteKit's load function before the component renders so social crawlers and first-paint users never see broken image slots.
Core pattern
on:error fallback in a Svelte component
Svelte makes image fallback straightforward with the on:error directive. Bind the src attribute to a let variable and update it in the error handler.
Keep the fallback value separate from the reactive src so you can check whether the error handler has already triggered — preventing an infinite loop if the fallback URL itself fails.
<!-- src/lib/components/FallbackImage.svelte -->
<script>
export let src;
export let alt;
export let width = 800;
export let height = 450;
const fallback = `https://fallback.pics/api/v1/${width}x${height}?text=Image+Not+Found`;
let currentSrc = src;
function handleError() {
if (currentSrc !== fallback) currentSrc = fallback;
}
</script>
<img
src={currentSrc}
{alt}
{width}
{height}
on:error={handleError}
/> Load function
Resolve missing images in SvelteKit load functions
SvelteKit's load function runs on the server for the initial request and on the client for subsequent navigation. Resolving fallback URLs here ensures the correct src reaches the template before the component mounts.
This is especially valuable for blog post pages and product detail pages where CMS data may have empty image fields.
// src/routes/blog/[slug]/+page.server.ts
export async function load({ params }) {
const post = await fetchPost(params.slug);
if (!post) error(404, 'Post not found');
return {
post: {
...post,
image: post.image
?? `https://fallback.pics/api/v1/1200x630.jpg?text=${encodeURIComponent(post.title)}`,
},
};
} Reusable component
Parameterize the fallback with props
A parameterized FallbackImage component accepts custom fallback dimensions and text for different use cases: blog thumbnails, product images, and user avatars each have different size requirements.
Make the fallback reactive with a $: computed declaration so it updates if width or height props change.
<!-- src/lib/components/FallbackImage.svelte (extended) -->
<script>
export let src;
export let alt;
export let width = 800;
export let height = 450;
export let fallbackText = 'Image+Not+Available';
$: fallback = `https://fallback.pics/api/v1/${width}x${height}?text=${fallbackText}`;
let currentSrc = src;
$: currentSrc = src; // reset when prop changes
function handleError() {
if (currentSrc !== fallback) currentSrc = fallback;
}
</script>
<img src={currentSrc} {alt} {width} {height} on:error={handleError} /> Avatar pattern
User avatar fallback with initials
User avatar slots are a common fallback case. When no profile image is set, display initials in a colored circle. The fallback.pics avatar route handles this without any additional component markup.
<!-- src/lib/components/Avatar.svelte -->
<script>
export let src;
export let name;
export let size = 48;
const initials = name.split(' ').map(n => n[0]).join('').toUpperCase().slice(0, 2);
const fallback = `https://fallback.pics/api/v1/avatar/${size}?text=${initials}`;
let currentSrc = src ?? fallback;
function handleError() {
if (currentSrc !== fallback) currentSrc = fallback;
}
</script>
<img
src={currentSrc}
alt="{name} avatar"
width={size}
height={size}
on:error={handleError}
style="border-radius: 50%"
/> OG image
Set og:image fallbacks in SvelteKit layouts
Use SvelteKit's page meta handling in +page.server.ts to pass og:image data down to the head. Resolve the fallback URL in the load function and use it in a +layout.svelte svelte:head block.
This ensures social crawlers and link preview bots receive a valid og:image on the server-rendered response.
<!-- +layout.svelte -->
<svelte:head>
{#if data.ogImage}
<meta property="og:image" content={data.ogImage} />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
{/if}
</svelte:head> Performance
Always declare width and height on img elements
Svelte does not add implicit width and height to img elements. An img without explicit dimensions causes layout shift when the image loads or when it is replaced by a fallback.
Pass width and height as props to your FallbackImage component and forward them to the img element. For content where dimensions vary, use aspect-ratio CSS to reserve space.
Key takeaways
What to standardize before shipping
- Use on:error in Svelte to swap src to a fallback URL when the image fails to load.
- Guard against infinite error loops by comparing currentSrc to the fallback value before updating.
- Resolve missing CMS image fields in the load function so fallback URLs are ready before the component mounts.
- Make FallbackImage a parameterized component with width, height, and fallbackText props for reuse across contexts.
- Always forward width and height props to the img element to prevent layout shift.
Production fallback layer
Use fallback.pics anywhere an image URL is accepted.
Start with one deterministic URL and standardize fallback behavior across your design system.