Simple Image Placeholders with SVG

Written by Tyler Sticka on

We do a lot of rapid prototyping at Cloud Four, which means we’re often working with incomplete or hypothetical content. When it comes to FPO images, we’ve relied on a few different solutions:

Each of these techniques has strengths and weaknesses. For us, external requests slowed down refreshes during local development, client-side libraries were more failure-prone and introduced modest performance hiccups, and it was a drag having to stop prototyping to go search for, resize and save stock images manually.

So I made a tiny, dependency-free library called Simple SVG Placeholder. It generates data URIs for placeholder img elements.

How It Works

Consider this typical placeholder image:

300×150

If you were to “hand code” this image as an SVG, it might look something like this:

<svg xmlns="http://www.w3.org/2000/svg" width="300" height="150" viewBox="0 0 300 150">
  <rect fill="#ddd" width="300" height="150"/>
  <text fill="rgba(0,0,0,0.5)" font-family="sans-serif" font-size="30" dy="10.5" font-weight="bold" x="50%" y="50%" text-anchor="middle">300×150</text>
</svg>

Our JavaScript function looks very similar, except we use template literals so that details like size, color and typography may be customized:

const str = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
  <rect fill="${bgColor}" width="${width}" height="${height}"/>
  <text fill="${textColor}" font-family="${fontFamily}" font-size="${fontSize}" dy="${dy}" font-weight="${fontWeight}" x="50%" y="50%" text-anchor="middle">${text}</text>
</svg>`;

Then we clean up and encode the string so it can be used as a Data URI. This portion takes a lot of inspiration from Filament Group’s SVG URI Encoder, but simplified since we know more about our source markup:

const cleaned = str
  .replace(/[\t\n\r]/gim, '') // Strip newlines and tabs
  .replace(/\s\s+/g, ' ') // Condense multiple spaces
  .replace(/'/gim, '\\i'); // Normalize quotes

const encoded = encodeURIComponent(cleaned)
  .replace(/\(/g, '%28') // Encode brackets
  .replace(/\)/g, '%29');

return `data:image/svg+xml;charset=UTF-8,${encoded}`;

The result is a string we can use as the src attribute for an img element!

How We Use It

As mentioned earlier, our greatest need for placeholder images is while prototyping. We do a lot of that work in-browser using some sort of template engine to streamline the process.

First, we install the Simple SVG Placeholder package:

npm i --save @cloudfour/simple-svg-placeholder

Then we use the function to build a template helper. If our project uses Handlebars, the helper might look like this:

// Include the function
const simpleSvgPlaceholder = require('@cloudfour/simple-svg-placeholder');

// Optionally establish project-specific defaults
const defaults = {
  bgColor: '#0F1C3F',
  textColor: '#7FDBFF'
};

// Register the helper
Handlebars.registerHelper('placeholderImage', block => {
  const options = block.hash || {};
  return simpleSvgPlaceholder({ ...defaults, ...options });
});

Then we can use our helper in templates:

<img src="{{placeholderImage width=800 height=450}}" alt="">

Which compiles to a data URI containing the placeholder image:

<img src="data:image/svg+xml;charset=UTF-8,..." alt="">

Which displays in the browser:

800×450

Start Holding Those Places

Simple SVG Placeholder has a bunch more options detailed in its README. It’s available now via GitHub, NPM, Yarn, and so on. I hope you dig it!

Tyler Sticka

Tyler Sticka is Cloud Four's VP of Design, allowing him to think about design systems every day. When he isn’t directing his team, sketching on sticky notes or nitpicking CSS, he enjoys reading comics, making video games and listening to weird music. He tweets as @tylersticka.

Never miss an article!

Get Weekly Digests


Leave a Comment

Please be kind, courteous and constructive. You may use simple HTML or Markdown in your comments. All fields are required.


Let’s discuss your project! Email Us