SyntaxStudy
Sign Up
Next.js Image Formats, Quality, and the Blur Placeholder
Next.js Beginner 1 min read

Image Formats, Quality, and the Blur Placeholder

Next.js image optimisation converts source images to WebP by default and to AVIF when the browser supports it. AVIF offers around 50% smaller file sizes compared to JPEG at equivalent quality. The quality prop controls the compression level as a number from 1 to 100, defaulting to 75. Reducing quality slightly (e.g., to 60 or 65) can significantly reduce file size with minimal visible difference for most images. The blur placeholder feature shows a low-resolution blurred version of the image while the full image loads, providing a much better loading experience than an empty space. For local images, setting placeholder="blur" is sufficient — Next.js generates the blurDataURL automatically. For remote images you must provide the blurDataURL prop yourself, typically a tiny base64-encoded image or a URL to a very small version of the image. The next.config.js imageSizes and deviceSizes arrays control the breakpoints used when generating srcset values. The default device sizes (640, 750, 828, 1080, 1200, 1920, 2048, 3840) cover most screen widths. You can customise these if your application serves unusual viewport sizes. The formats array in the images config can be used to control which output formats Next.js produces.
Example
// next.config.js — image configuration
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    // Control output formats (default includes webp)
    formats: ['image/avif', 'image/webp'],

    // Custom device sizes for responsive images
    deviceSizes: [640, 750, 828, 1080, 1200, 1920],

    // Custom image sizes for fixed-width images
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],

    // Minimum cache TTL in seconds (default: 60)
    minimumCacheTTL: 86400, // 24 hours

    remotePatterns: [
      { protocol: 'https', hostname: 'images.unsplash.com' },
    ],
  },
};
module.exports = nextConfig;

// Remote image with manual blurDataURL
import Image from 'next/image';

interface BlogPost {
  title: string;
  coverImage: string;
  blurHash: string; // tiny base64 JPEG from your API
}

export default function BlogCover({ post }: { post: BlogPost }) {
  return (
    <div className="relative w-full h-64">
      <Image
        src={post.coverImage}
        alt={post.title}
        fill
        quality={65}
        placeholder="blur"
        blurDataURL={post.blurHash}
        sizes="(max-width: 768px) 100vw, 800px"
        className="object-cover"
        priority
      />
    </div>
  );
}