Transparent Pixels

I became interested in image replacement techniques to keep page size down, AJAXing in full images later as needed, and I stumbled across The Smallest Transparent Pixel. Using a bas64 encoded 1x1 transparent pixel as a placeholder, you set the width and height attributes to the space you want to fill.

  <img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw" width="200" height="150" />

Unfortunately, the 1x1 pixel images have issues with common responsive styles, due to the image's square aspect ratio.

Let's say you set img { max-width: 100%; } to prevent images from causing horizontal scrolling on small screens. Your 1x1 pixel img's width can be squished down below what you set in the width attribute, but the height remains the same, leaving you with an oddly shaped placeholder.

If you try to correct this with img { max-width: 100%; height: auto; }, the height attribute is completely ignored, and the width can be squished below the width attribute's setting, leaving you with a square; probably not the aspect ratio you intended.

This is intended behavior in the browser and works great for regular images, but how can we fix this for this filler image?

SVG to the Rescue

GIFs and PNGs aren't the only images you can inline. Our friend SVG can even be inlined without base64. SVG also has an aspect ratio built in using the viewBox attribute. So if we swap out our 1x1 pixel for this...

  <img src="data:image/svg+xml;charset=utf-8,%3Csvg xmlns%3D'' viewBox%3D'0 0 200 150'%2F%3E" width="200" height="150" />

...our responsive styles work as intended! The important bit is the 116 byte src attribute. This works all the way back to IE9 due to the encodedURIComponent conversion of special characters, which unfortunately makes it a little more difficult to read.

Notice how the responsively sized svg maintains its aspect ratio. This is set here viewBox%3D'0 0 200 150', giving the svg a width (200) and height (150) to get the correct aspect ratio. This could be viewBox%3D'0 0 16 9' for 16x9 images or the exact width and height of the image you plan to use as a replacement.

Image Replacement

The above is a great snippet by itself to be used in place of the standard 1x1 pixel image, but how can we apply this to image replacement?

  <figure class="image-replacement" data-src="" data-width="1400" data-height="900">
  <noscript><img src="" width="1400" height="900" /></noscript>

In our HTML, we have a figure tag with the relevant image info set in data attributes for our Javascript to pull. There's a simple noscript fallback so that our Javascript-less bretheren don't suffer.

The placeholder svg has been updated to display an icon instead of just being blank, but the technique is still the same of setting the correct viewBox. The icon itself is a symbol which has its own viewBox, allowing it to be easily sized and centered in the main svg. Unfortunately, the symbol can't be defined or reused outside of the individual img, since it seems that browsers treat it as an external, self contained file.

The Javascript is very minimal, taking the data attributes of the figure to create the placeholder, then loading the image when hovered, mainly to show how the image seamlessly replaces the placeholder. The content doesn't have to reflow and text doesn't jump around. For a real image replacement scenario, you'd likely want to configure it to load images as they come into viewport, or perhaps when they're next in the slideshow.

Summary and Closing

Use data:image/svg+xml;charset=utf-8,%3Csvg xmlns%3D'' viewBox%3D'0 0 200 150'%2F%3E as the placeholder src attribute for any image you need to replace, updating the viewBox value to keep the correct aspect ratio.

There are other ways you can accomplish all of this, but this technique is ultra simple, self-contained and can likely be used outside of image replacement.

Comment below if you have any improvements or examples of other uses.