Next.js Image Fallbacks Without Layout Shift
Build Next.js image fallbacks that handle missing src values, failed remote images, SVG placeholders, width and height, fill layouts, and CLS-safe fallback URLs.
Next.js image fallback work has two jobs: replace missing or failed media and keep the reserved image geometry stable.
A good fallback component handles missing src values before render, failed remote images after render, Next.js remote image configuration, and SVG placeholder URLs without causing layout shift.
Search intent
Why Next.js image fallback is a layout problem
Developers search for Next.js image fallback when remote CMS, ecommerce, avatar, or API images fail. In Next.js, the fix is not only changing src. The fallback must keep the same width, height, or fill container so the page does not shift when the image state changes.
The Next.js Image component uses width and height to infer aspect ratio and reserve space. If your fallback source has different dimensions or you remove the sizing contract, you can trade a broken image for a Core Web Vitals problem.
Missing source data
Use a fallback URL before rendering Image when CMS or product data has no usable src.
Failed remote loads
Use a client component and state guard when an image URL exists but fails after render.
CLS control
Keep width, height, fill container, and aspect ratio stable when swapping to the fallback.
Config
Allow fallback.pics as a remote image source
If you use next/image with remote fallback URLs, configure the fallback.pics hostname in next.config.js. Keep the pattern specific instead of allowing every remote hostname.
fallback.pics returns generated SVG placeholders from the /api/v1 route. Use unoptimized on the Image component for these fallback URLs so Next.js serves the SVG source as-is.
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: "https",
hostname: "fallback.pics",
pathname: "/api/v1/**",
},
{
protocol: "https",
hostname: "cdn.example.com",
pathname: "/products/**",
},
],
},
}; Baseline
Handle missing src before rendering next/image
Missing src values are a data problem, not a load-error problem. Resolve the fallback source before rendering Image so the component always receives a valid src.
Match the fallback URL dimensions to the Image width and height. In a square product grid, use a square fallback URL.
import Image from "next/image";
const productFallback =
"https://fallback.pics/api/v1/800x800?text=Product+Image";
export function ProductImage({
src,
alt,
}: {
src?: string | null;
alt: string;
}) {
const imageSrc = src?.trim() ? src : productFallback;
return (
<Image
src={imageSrc}
width={800}
height={800}
alt={alt}
unoptimized={imageSrc === productFallback}
/>
);
} Client component
Handle failed remote images with onError
A remote image can still fail after render because the file was deleted, the CDN returned an invalid response, or the host blocked the request. In the App Router, put load-failure fallback logic in a client component.
Guard the state update so the fallback does not retry forever if the fallback source is already active.
"use client";
import Image, { type ImageProps } from "next/image";
import { useState } from "react";
type SafeImageProps = Omit<ImageProps, "src" | "alt"> & {
src?: string | null;
fallbackSrc: string;
alt: string;
};
export function SafeImage({
src,
fallbackSrc,
alt,
...props
}: SafeImageProps) {
const [currentSrc, setCurrentSrc] = useState(src || fallbackSrc);
return (
<Image
{...props}
src={currentSrc}
alt={alt}
unoptimized={currentSrc === fallbackSrc}
onError={() => {
if (currentSrc !== fallbackSrc) {
setCurrentSrc(fallbackSrc);
}
}}
/>
);
} Cards
Use width and height for fixed-ratio surfaces
For product cards, article thumbnails, user avatars, and dashboard previews, pass width and height even when CSS controls the rendered size. Next.js uses those values to infer aspect ratio and reserve the right space.
Use CSS to scale the image responsively, but do not drop the intrinsic dimensions from the Image component.
<SafeImage
className="productImage"
src={product.imageUrl}
fallbackSrc="https://fallback.pics/api/v1/800x800?text=Product+Image"
width={800}
height={800}
alt={product.name}
/>
/* CSS */
.productImage {
display: block;
width: 100%;
height: auto;
object-fit: cover;
} Fill layouts
Use fill only inside a stable container
Use fill when the rendered size is controlled by the parent container. The parent must reserve space with position: relative and a stable aspect-ratio or fixed dimensions.
The fallback URL should still match the intended aspect ratio. For a 3:2 card image, use a 600x400 fallback URL; for an Open Graph style preview, use 1200x630.
<div className="mediaFrame">
<SafeImage
src={article.coverUrl}
fallbackSrc="https://fallback.pics/api/v1/1200x630?text=Article+Image"
fill
sizes="(max-width: 768px) 100vw, 50vw"
alt={article.title}
/>
</div>
/* CSS */
.mediaFrame {
position: relative;
width: 100%;
aspect-ratio: 1200 / 630;
overflow: hidden;
}
.mediaFrame img {
object-fit: cover;
} Surfaces
Choose fallback URLs by Next.js surface
A single fallback label can work for early development, but production interfaces scan better when each image surface has its own dimensions and message.
Keep labels generic and public. Do not include email addresses, user names, order numbers, account IDs, tokens, or other private values in placeholder URL text.
const fallbackBySurface = {
product: "https://fallback.pics/api/v1/800x800?text=Product+Image",
avatar: "https://fallback.pics/api/v1/avatar/96?text=User",
article: "https://fallback.pics/api/v1/1200x630?text=Article+Image",
banner: "https://fallback.pics/api/v1/1200x400?text=Banner",
unavailable: "https://fallback.pics/api/v1/600x400?text=Image+Unavailable",
}; Tradeoffs
When to use img instead of next/image
Use next/image when you need Next.js image optimization, responsive srcsets, priority handling, and consistent framework behavior. Use a plain img when the image is already a small generated SVG placeholder and you do not need Next.js to manage it.
In mixed components, it is reasonable to use next/image for real product media and a plain img for a static SVG fallback if that keeps the implementation simpler. The important requirement is the same: reserve the dimensions before the image loads.
<img
src="https://fallback.pics/api/v1/600x400?text=Image+Unavailable"
width="600"
height="400"
alt="Image unavailable"
loading="lazy"
decoding="async"
/> Internal links
Where to go next
Use this article when designing a layout-safe Next.js image fallback component. The shorter Next.js guide is useful for quick reference, and the API syntax guide covers dimensions, colors, avatars, and text labels.
If your issue is plain HTML or React without next/image, use the HTML onerror and React fallback guides instead.
Next.js guide: https://fallback.pics/guides/nextjs-image-fallback/
React guide: https://fallback.pics/guides/react-image-fallback/
HTML onerror guide: https://fallback.pics/guides/img-onerror-fallback/
Placeholder image API: https://fallback.pics/placeholder-image-api/
Broken image fallback: https://fallback.pics/broken-image-fallback/
API reference: https://fallback.pics/api/ Key takeaways
What to standardize before shipping
- Resolve missing src values before rendering next/image.
- Use a client component with an onError state guard for failed remote image loads.
- Keep width and height, or a stable fill container, so fallbacks do not cause layout shift.
- Use unoptimized for fallback.pics SVG placeholder URLs rendered through next/image.
- Keep placeholder URL text generic and safe for logs, screenshots, and analytics.
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.