Every developer needs placeholder images during prototyping. Explore all your options — external services, SVG data URIs, CSS-only placeholders — and when to use each.
Real content comes late in the development process. But you need images to build layouts, test responsiveness, and review designs. The placeholder you choose affects your workflow: external services add network latency and can break offline; SVG data URIs are instant but require generation; CSS-only solutions are simplest but least realistic.
The most realistic option — actual photographs with correct aspect ratios.
<!-- Random photo, 800×400 pixels -->
<img src="https://picsum.photos/800/400" alt="">
<!-- Consistent image (seed-based) -->
<img src="https://picsum.photos/seed/42/800/400" alt="">
<!-- Grayscale -->
<img src="https://picsum.photos/800/400?grayscale" alt="">
<!-- Blur -->
<img src="https://picsum.photos/800/400?blur=2" alt="">
Shows the dimensions directly on the image — useful for wireframes.
<img src="https://placehold.co/600x400" alt="">
<img src="https://placehold.co/600x400/FF0000/FFF?text=Hero+Image" alt="">
Cons: Requires network access; service could go down; CORS issues in some environments.
SVG data URIs embed the image directly in the src attribute — no requests, no dependencies, works offline.
function placeholderSVG({ width = 400, height = 300, bg = "#e2e8f0", text = "Image" } = {}) {
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}">
<rect width="100%" height="100%" fill="${bg}"/>
<text
x="50%" y="50%"
dominant-baseline="middle"
text-anchor="middle"
font-family="system-ui, sans-serif"
font-size="${Math.min(width, height) * 0.1}px"
fill="#94a3b8">${text || `${width}×${height}`}
</text>
</svg>`
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`
}
// Usage
<img src={placeholderSVG({ width: 800, height: 400, text: "Blog Header" })} alt="">
When you need a colored block without any actual image — works for background areas and avatar placeholders.
.placeholder {
background: linear-gradient(135deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);
background-size: 200% 200%;
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
<!-- Aspect-ratio box that reserves correct space -->
<div class="placeholder" style="aspect-ratio: 16/9; border-radius: 8px;"></div>
For production Next.js apps, generate blur placeholders at build time to prevent layout shift:
import { getPlaiceholder } from "plaiceholder"
const { base64 } = await getPlaiceholder(imageBuffer)
// The base64 is a tiny (4×3px) blurred version of the real image
<Image
src="/hero.jpg"
alt="Hero"
placeholder="blur"
blurDataURL={base64}
width={1200}
height={630}
/>
| Scenario | Best Option |
|---|---|
| Realistic photo layout review | Lorem Picsum |
| Wireframes with size labels | Placehold.co |
| Offline or CI environments | SVG data URI |
| Loading state / skeleton | CSS shimmer animation |
| Production Next.js app | BlurDataURL with plaiceholder |
| Avatar / user photo fallback | Initials SVG (see below) |
function initialsAvatar(name, size = 40) {
const initials = name.split(" ").map(w => w[0]).join("").slice(0, 2).toUpperCase()
const hue = name.split("").reduce((acc, c) => acc + c.charCodeAt(0), 0) % 360
const bg = `hsl(${hue}, 55%, 55%)`
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${size}" height="${size}">
<rect width="100%" height="100%" rx="${size / 2}" fill="${bg}"/>
<text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle"
font-family="system-ui" font-size="${size * 0.38}px" font-weight="600" fill="white"
>${initials}</text>
</svg>`
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`
}
// Use as fallback when user has no photo
const avatarSrc = user.photoUrl ?? initialsAvatar(user.name)
Generate custom placeholder images instantly at any size with HeoLab's Placeholder Image Generator.
External services like Lorem Picsum are great for realistic design reviews, but SVG data URIs are the most reliable for prototyping — they work offline, require no network requests, and can be generated programmatically. For loading states, CSS shimmer animations provide the best user experience. In production Next.js apps, always use blurDataURL to eliminate layout shift as real images load.