Zach’s ugly mug (his face) Zach Leatherman

A New Technique for Image Optimization: SVG Short Circuiting

November 15, 2023

Working on an Image Optimization tutorial for CloudCannon (using Eleventy), I stumbled into what I think is a neat little trick for automated image optimization.

There are three kinds of optimization that Eleventy Image can do:

  1. Raster to raster: Convert a large raster input image (PNG, JPEG, WebP, AVIF, etc) into smaller raster output images (pretty standard).
    • One nice feature here is that Eleventy Image will automatically swap between <img> and <picture> for you automatically based on the combination of output formats and widths options you’ve used for any specific image.
  2. Vector to raster: Convert a large vector image (SVG) into smaller sized raster outputs (again, pretty standard).
    • This also includes an option to leave SVG inputs as SVG-only (skipping raster outputs altogether) with svgShortCircuit: true.
  3. Vector to raster/vector: this new approach uses svgShortCircuit: "size" to convert a large vector image (SVG) into a mixture of vector and raster outputs while discarding the raster images that are larger in file weight than their vector counterpart.

Read more about the Eleventy Image options for SVG.

Astute readers might remember the post Vector? Raster? Why not Both! which detailed an approach to manually subset and overlay an image as two separate layers: a vector layer and a raster layer.

SVG Short Circuiting Examples

Mexico

The Mexico Flag is a pretty complex SVG (139.55 kB uncompressed). If we use Eleventy Image, we can look at the output images:

Size Format Percent Width
53 kB (Brotli compressed) svg 100% 980w
56.28 kB (Discarded) jpeg 106.19% 1600w
31.07 kB webp 58.63% 1600w
18.52 kB avif 34.95% 1600w
6.68 kB jpeg 12.60% 400w
3.85 kB webp 7.27% 400w
3.39 kB avif 6.39% 400w

When using svgShortCircuit: "size" and svgCompressionSize: "br", the largest JPEG is discarded from the output as its file size is larger than the SVG. We prefer the vector output!

Here’s what the generated markup looks like:

<picture>
	<source type="image/avif" srcset="1IB2wrqzRT-400.avif 400w, 1IB2wrqzRT-1600.avif 1600w" sizes="">
	<source type="image/webp" srcset="1IB2wrqzRT-400.webp 400w, 1IB2wrqzRT-1600.webp 1600w" sizes="">
	<source type="image/jpeg" srcset="1IB2wrqzRT-400.jpeg 400w, 1IB2wrqzRT-980.svg 980w" sizes="">
	<source type="image/svg+xml" srcset="1IB2wrqzRT-980.svg 980w" sizes="">
	<img src="1IB2wrqzRT-400.jpeg" alt="Flag of Mexico" width="980" height="560" loading="eager" decoding="async">
</picture>

(sizes attribute omitted for clarity)

This approach is somewhat experimental (and is not enabled by default in Eleventy Image), although it works well in practice. This technique involves replacing large raster formats in <source> with SVG. Specifically, you might notice the image/jpeg type above has an SVG image included: <source type="image/jpeg" srcset="1IB2wrqzRT-400.jpeg 400w, 1IB2wrqzRT-980.svg 980w">.

Tiger

The Ghostscript Tiger is less complex (68.63 kB uncompressed) but still benefits from SVG short circuiting. Let’s look at the Eleventy Image output here:

Size Format Percent Width
19.63 kB (Brotli compressed) svg 100% 900w
254.67 kB (Discarded) jpeg 1297.30% 1600w
179.77 kB (Discarded) webp 915.77% 1600w
81.36 kB (Discarded) avif 414.43% 1600w
38.84 kB (Discarded) jpeg 197.84% 400w
35.04 kB (Discarded) webp 178.49% 400w
21.28 kB (Discarded) avif 108.41% 400w

Using this technique, the output HTML looks like this:

<img src="59IGmw9rii-900.svg" alt="Ghostscript Tiger" width="900" height="900" loading="eager" decoding="async">

After size comparisons, only the vector is used in the final output and all of the raster outputs are discarded—the markup is simplified to an <img>.

The output above using svgShortCircuit: "size" is identical to the output if we had used svgShortCircuit: true to automatically discard the raster outputs. At some point in the future we may have a feature that uses heuristics to swap between "size" and true to avoid unnecessary image processing.

It should be noted that this image optimization technique only works for build-time image optimizations and is a great example of how a build step can take the performance of your web site beyond what request-time image optimization is capable of.

Demo

Screenshot image for https://v1.screenshot.11ty.dev/https%3A%2F%2Fgnarly-ginger.cloudvent.net%2F/opengraph//

With a nod to the tech stack, here are a few things I used to construct the demo:

Walkthrough on YouTube

Watch on YouTube: Stop worrying about huge image uploads with Eleventy Image and CloudCannon CMS

Originally posted on:

Screenshot image for https://v1.screenshot.11ty.dev/https%3A%2F%2Fcloudcannon.com%2Fblog%2Fautomatically-optimize-your-images-with-eleventy-image-and-cloudcannon%2F/opengraph//

< Newer
An Attempted Taxonomy of Web Components
Older >
The Commit that Updated a Thousand Demos

Zach Leatherman IndieWeb Avatar for https://zachleat.com/is a builder for the web at IndieWeb Avatar for https://fontawesome.com/Font Awesome and the creator/maintainer of IndieWeb Avatar for https://www.11ty.devEleventy (11ty), an award-winning open source site generator. At one point he became entirely too fixated on web fonts. He has given 84 talks in nine different countries at events like Beyond Tellerrand, Smashing Conference, Jamstack Conf, CSSConf, and The White House. Formerly part of CloudCannon, Netlify, Filament Group, NEJS CONF, and NebraskaJS. Learn more about Zach »

15 Reposts

IndieWeb Avatar for https://businesswebsites199.comIndieWeb Avatar for https://exoticdigitalaccess.co.keIndieWeb Avatar for https://businesswebsites199.comIndieWeb Avatar for https://soatdev.comIndieWeb Avatar for https://vermaden.wordpress.comJean Pierre KolbRichConor C. Peterson ????nucliwebJakub Iwanowski :bash:Zach LeathermanIndieWeb Avatar for https://zerobytes.monsterJonEleventy ???? v2.0.1Doctor Popular

23 Likes

haliphax ????Jean Pierre KolbAngela "Ge" RicciConor C. Peterson ????Thomas Maria HelzlenucliwebPhilip ZastrowKrzysztof JeziornyJakub Iwanowski :bash:Nelson Chu PavloskyRaffael JescheJustin PoehneltJonAmelia Bellamy-RoydsSimon Cox :SEO:Connor BärHeinz WittenbrinkTim Severien - open to workDee-Yell (Dave)Eleventy ???? v2.0.1Ashur CabreraCloudCannonDoctor Popular
2 Comments
  1. Ashur Cabrera

    @zachleat say no more fam``` <svg> <image href="beefy.png” /> </svg> ```

  2. Zach Leatherman

    @ashur well wait a second

Shamelessly plug your related post

These are webmentions via the IndieWeb and webmention.io.

Sharing on social media?

This is what will show up when you share this post on Social Media:

How did you do this? I automated my Open Graph images. (Peer behind the curtain at the test page)