Blog Next.js Guides 14 min read

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 fallbacknext/imageCLSPlaceholder images
Next.js Image Fallbacks Without Layout Shift

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.

Implementation text
// 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.

Implementation tsx
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.

Implementation tsx
"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.

Implementation text
<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.

Implementation text
<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.

Implementation tsx
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.

Implementation text
<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.

Implementation text
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.

Read the docs